From 7d6a00ea4c19cdbf93c8a15ad870306cfe2e6b7e Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 29 Oct 2024 11:46:58 +0100 Subject: [PATCH] fix: refs #4452 Lost connection with db --- README.md | 30 ++++++++++++++++------------ worker/worker.js | 47 +++++++++++++++++--------------------------- worker/workerPool.js | 38 ++++++++++------------------------- 3 files changed, 45 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index ed7fca8..884d422 100644 --- a/README.md +++ b/README.md @@ -34,19 +34,23 @@ Este proyecto es una aplicación backend que utiliza Node.js, Docker, MariaDB y 4. Crea un archivo `.env` en el directorio raíz del proyecto y configura las variables de entorno necesarias: ```env - # DEBUG = 1 - # KEEP_TMP_FILES = 1 - # DRY_PRINT = 1 - DB_HOST = mariadb - DB_PORT = 3306 - DB_USER = user - DB_PASSWORD = password - DB_NAME = name - DB_PRINTER_SCHEMA = name - WORKERS = 10 - GET_RECORD_DELAY = 4000 - PRINTER_TIMEOUT = 1000 - PRINTER_PORT = 9100 + # DEBUG=1 + # KEEP_TMP_FILES=1 + # DRY_PRINT=1 + DB_HOST=mariadb + DB_PORT=3306 + DB_USER=user + DB_PASSWORD=password + DB_NAME=name + DB_PRINTER_SCHEMA=name + WORKERS=10 + REPLACE_WORKER_DELAY=10000 + DB_RECORD_DELAY=6000 + DB_CONN_DELAY=2000 + DB_CONN_ATTEMPTS=1 + PRINTER_CONN_TIMEOUT=1000 + PRINTER_CONN_ATTEMPTS=2 + PRINTER_CONN_PORT=9100 ``` ## Descripción de Archivos diff --git a/worker/worker.js b/worker/worker.js index eadc589..b762742 100644 --- a/worker/worker.js +++ b/worker/worker.js @@ -8,8 +8,7 @@ const generateZPL = require('../resources/zplTemplate'); const label = require('../resources/label.json'); const log = require('../log') -// Función para obtener una conexión con reintentos -async function getConn(retries = 3, delay = 5000) { +async function getConn(retries = Number(env.DB_CONN_ATTEMPTS), delay = Number(env.DB_CONN_DELAY)) { let attempt = 0; while (attempt < retries) { try { @@ -17,20 +16,19 @@ async function getConn(retries = 3, delay = 5000) { } catch (error) { attempt++; if (attempt >= retries) - throw new Error('No se pudo obtener conexión después de múltiples intentos.'); + throw new Error('Could not get connection'); await new Promise(resolve => setTimeout(resolve, delay)); } } } - -async function sendZPL(zplContent, ipAddress, retries = 2) { +async function sendZPL(zplContent, ipAddress, retries = Number(env.PRINTER_CONN_ATTEMPTS)) { try { const result = await new Promise((resolve, reject) => { const client = new net.Socket(); - client.setTimeout(Number(env.PRINTER_TIMEOUT)); + client.setTimeout(Number(env.PRINTER_CONN_TIMEOUT)); - client.connect(Number(env.PRINTER_PORT), ipAddress, () => { + client.connect(Number(env.PRINTER_CONN_PORT), ipAddress, () => { if (!env.DRY_PRINT) client.write(zplContent, () => { client.destroy(); @@ -43,13 +41,13 @@ async function sendZPL(zplContent, ipAddress, retries = 2) { }); client.on('timeout', () => { - log('error', 'Tiempo de espera agotado al conectar con la impresora'); + log('error', 'Connection to the printer timed out'); client.destroy(); reject('error'); }); client.on('error', error => { - log('error', `Error al enviar ZPL a la impresora: ${error.message || error}`); + log('error', `Error sending ZPL to the printer: ${error.message || error}`); client.destroy(); reject('error'); }); @@ -57,18 +55,15 @@ async function sendZPL(zplContent, ipAddress, retries = 2) { if (result === 'success') return true; } catch (error) { - if (error !== 'error') - log('error', `Error inesperado al enviar ZPL a la impresora: ${error.message || error}`); if (retries > 0) { - log('debug', `Reintentando... Quedan ${retries} intentos.`); + log('debug', `Retrying... ${retries} attempts remaining`); return sendZPL(zplContent, ipAddress, retries - 1); } else { - log('error', 'Todos los intentos fallaron. No se pudo enviar el ZPL.'); + log('error', 'All attempts failed. Unable to send ZPL.'); return false; } } } - async function getPrinterIp(printerFk, conn) { try { const [rows] = await conn.query(` @@ -77,14 +72,13 @@ async function getPrinterIp(printerFk, conn) { WHERE id = ? `, [printerFk]); if (!rows.length) - throw new Error(`No se encontró la impresora con id = ${printerFk}`); + throw new Error(`Printer with ID ${printerFk} not found`); return rows[0].ipAddress; } catch (error) { - log('error', 'Error al obtener la dirección IP de la impresora:', error); + log('error', `Error retrieving the printer IP address:`, error); throw error; } } - async function getRecord() { const conn = await getConn(); try { @@ -104,17 +98,16 @@ async function getRecord() { return record; } catch (error) { await conn.rollback(); - log('error', 'Error al obtener y marcar el registro para procesamiento:', error); + log('error', 'Unable to retrieve and mark the record:', error); return; } finally { conn.release(); } } - async function processRecord(record) { const conn = await getConn(); try { - log('debug', `(${record.expeditionFk}) Procesando...`); + log('debug', `(${record.expeditionFk}) Processing...`); const zplData = generateZPL(record, label); if (env.KEEP_TMP_FILES) { @@ -129,21 +122,20 @@ async function processRecord(record) { if (isSendResult) { await updateState(conn, record.expeditionFk, 11) - log('success', `(${record.expeditionFk}) Impresión realizada correctamente`); + log('success', `(${record.expeditionFk}) Print completed successfully`); } else { await updateState(conn, record.expeditionFk, 13) - log('error', `(${record.expeditionFk}) Error en la impresión`); + log('error', `(${record.expeditionFk}) Print not completed`); } parentPort.postMessage('done'); } catch (error) { - log('error', `Error al procesar el registro ${error}`); + log('error', `Unable to process the record ${error}`); await updateState(conn, record.expeditionFk, 13) parentPort.postMessage('error'); } finally { conn.release(); } } - async function updateState(conn, expeditionId, state) { await conn.query(` UPDATE expedition_PrintOut @@ -151,8 +143,6 @@ async function updateState(conn, expeditionId, state) { WHERE expeditionFk = ? `, [state, expeditionId]); } - -// Escuchar mensajes del hilo principal parentPort.on('message', async msg => { if (msg === 'check') { const record = await getRecord(); @@ -161,8 +151,7 @@ parentPort.on('message', async msg => { else { setTimeout(async() => { parentPort.postMessage('done'); - }, Number(env.GET_RECORD_DELAY)); + }, Number(env.DB_RECORD_DELAY)); } - } else - processRecord(msg).catch(err => log('error', 'Error en el worker:', err)); + } }); diff --git a/worker/workerPool.js b/worker/workerPool.js index b3b4e1d..23c817d 100644 --- a/worker/workerPool.js +++ b/worker/workerPool.js @@ -9,55 +9,37 @@ class WorkerPool { this.workers = []; this.initWorkers(numWorkers); } - - // Inicializar workers initWorkers(number) { for (let i = 0; i < number; i++) this.createWorker(); } - - // Crear un nuevo worker y manejar sus mensajes createWorker() { const worker = new Worker('./worker/worker.js'); worker.on('message', async msg => { - if (msg === 'done' || msg === 'error') + if (['done', 'error'].includes(msg)) worker.postMessage('check'); }); worker.on('error', error => { - log('error', 'Error en el worker:', error); + log('error', `Worker: ${error.message}`); this.replaceWorker(worker); }); - worker.on('exit', code => { - if (code !== 0) { - log('error', `Worker stopped with exit code ${code}`); - setTimeout(() => { - this.replaceWorker(worker); - }, 1000); - } else { - this.workers = this.workers.filter(worker => worker !== worker); - } - }); this.workers.push(worker); + worker.postMessage('check'); } - - // Reemplazar un worker fallido - replaceWorker(failedWorker) { - this.workers = this.workers.filter(worker => worker !== failedWorker); - log('debug', 'Replacing a worker...'); - this.createWorker(); + replaceWorker(worker) { + this.workers = this.workers.filter(w => w !== worker); + worker.terminate(); + setTimeout(async() => { + log('debug', 'Replacing worker...'); + this.createWorker(); + }, Number(env.REPLACE_WORKER_DELAY)); } - - // Asignar tareas iniciales a los workers async start() { const decoration = '△▽'.repeat(10); const rfidnatura = chalk.white.bold('Rfid') + chalk.green.bold('Natura') log(null, `${decoration} ${rfidnatura} ${decoration}`); if (env.DRY_PRINT) log('info', 'Dry print mode') - for (const worker of this.workers) - worker.postMessage('check'); // Pedir al worker que verifique nuevos registros } - - // Cerrar todos los workers end() { try { for (const worker of this.workers) worker.terminate();