fix: refs #4452 Lost connection with db
This commit is contained in:
parent
c087b0920a
commit
7d6a00ea4c
30
README.md
30
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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue