feat: refs #4452 vn changes

This commit is contained in:
Guillermo Bonet 2024-10-29 09:44:04 +01:00
parent afcb079407
commit cfa9b068ca
2 changed files with 33 additions and 83 deletions

View File

@ -1,4 +1,4 @@
# Backend Application
# RfidNatura (Print Server RFID)
Este proyecto es una aplicación backend que utiliza Node.js, Docker, MariaDB y worker threads para gestionar la impresión de etiquetas ZPL.
@ -8,15 +8,12 @@ Este proyecto es una aplicación backend que utiliza Node.js, Docker, MariaDB y
- [Uso](#uso)
- [Descripción de Archivos](#descripción-de-archivos)
- [main.js](#mainjs)
- [docker-compose.yml](#docker-composeyml)
- [Dockerfile](#dockerfile)
- [worker.js](#workerjs)
- [workerPool.js](#workerpooljs)
- [pool.js](#pooljs)
- [zplTemplate.js](#zpltemplatejs)
- [package.json](#packagejson)
- [label.json](#labeljson)
- [Dependencias](#dependencias)
## Instalación
@ -37,6 +34,9 @@ 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
@ -44,21 +44,11 @@ Este proyecto es una aplicación backend que utiliza Node.js, Docker, MariaDB y
DB_NAME = name
DB_PRINTER_SCHEMA = name
WORKERS = 10
# DEBUG = 1
# KEEP_TMP_FILES = 1
# DRY_PRINT = 1
GET_RECORD_DELAY = 4000
PRINTER_TIMEOUT = 1000
PRINTER_PORT = 9100
```
## Uso
1. Levanta los servicios de Docker:
```sh
docker-compose up --build
```
2. La aplicación backend estará disponible en `http://localhost:3000`.
## Descripción de Archivos
### `main.js`
@ -70,25 +60,6 @@ Este es el archivo de entrada principal que inicializa y comienza el procesamien
- **workerPool**: Se instancia un nuevo `WorkerPool` con el número de threads definido.
- **start**: Se llama al método `start` para asignar las tareas iniciales a los workers.
### `docker-compose.yml`
Define los servicios de Docker necesarios para la aplicación.
- **version**: Especifica la versión del formato de `docker-compose`.
- **services**: Define los servicios que se ejecutarán.
- **mariadb**: Servicio para la base de datos MariaDB.
- **backend**: Servicio para el backend de la aplicación.
### `Dockerfile`
Define cómo construir la imagen Docker para el servicio de backend.
- **FROM**: Utiliza la imagen base de Node.js más reciente.
- **COPY**: Copia los archivos de configuración y el código de la aplicación al contenedor.
- **RUN**: Instala las dependencias necesarias.
- **EXPOSE**: Expone el puerto 3000.
- **CMD**: Comando por defecto para iniciar la aplicación.
### `worker.js`
Maneja el procesamiento de registros de impresión y la comunicación con las impresoras.
@ -126,10 +97,6 @@ Genera las etiquetas ZPL basadas en los registros y la plantilla de etiquetas.
- **upperCaseRecord**: Convierte todos los valores de texto del registro a mayúsculas.
- **result**: Contiene el ZPL generado para cada etiqueta.
### `package.json`
Este archivo define las configuraciones básicas de tu proyecto backend, las dependencias necesarias para su funcionamiento, y las herramientas de desarrollo necesarias para mantener la calidad del código. Cada dependencia tiene un rol específico que ayuda a la aplicación a operar de manera eficiente y segura tanto en el desarrollo como en la producción.
### `label.json`
Este archivo define el formato y los mapeos necesarios para la generación de etiquetas ZPL. Si deseas cambiar los datos que se pasan a ZPL para la impresión de etiquetas, siempre debes seguir este formato. El `label.json` tiene la siguiente estructura:
@ -140,7 +107,4 @@ Este archivo define el formato y los mapeos necesarios para la generación de et
- **zpl**: Código ZPL que define el diseño de la etiqueta. Dentro del código ZPL, los valores de los mapeos se deben utilizar para ser reemplazados dinámicamente.
- **density**: La densidad de impresión.
- **width**: Ancho de la etiqueta.
- **height**: Altura de la etiqueta.
### `devDependencies`
Estas son las bibliotecas necesarias solo durante el desarrollo y no en producción.
- **height**: Altura de la etiqueta.

View File

@ -25,13 +25,12 @@ async function getConn(retries = 3, delay = 5000) {
}
async function sendZPL(zplContent, ipAddress, retries = 2) {
const port = 9100;
try {
const result = await new Promise((resolve, reject) => {
const client = new net.Socket();
client.setTimeout(1000);
client.setTimeout(Number(env.PRINTER_TIMEOUT));
client.connect(port, ipAddress, () => {
client.connect(Number(env.PRINTER_PORT), ipAddress, () => {
if (!env.DRY_PRINT)
client.write(zplContent, () => {
client.destroy();
@ -65,7 +64,7 @@ async function sendZPL(zplContent, ipAddress, retries = 2) {
return sendZPL(zplContent, ipAddress, retries - 1);
} else {
log('error', 'Todos los intentos fallaron. No se pudo enviar el ZPL.');
return 'error';
return false;
}
}
}
@ -86,46 +85,35 @@ async function getPrinterIp(printerFk, conn) {
}
}
async function getRecord(retries = 5, delay = 4000) {
for (let attempt = 0; attempt < retries; attempt++) {
const conn = await getConn();
try {
await conn.beginTransaction();
const [rows] = await conn.query(`
SELECT * FROM expedition_PrintOut
WHERE isPrinted = 10
LIMIT 1 FOR UPDATE
`);
if (!rows.length) {
await conn.commit();
return;
}
const record = rows[0];
await updateState(conn, record.expeditionFk, 12)
async function getRecord() {
const conn = await getConn();
try {
await conn.beginTransaction();
const [rows] = await conn.query(`
SELECT * FROM expedition_PrintOut
WHERE isPrinted = 10
LIMIT 1 FOR UPDATE
`);
if (!rows.length) {
await conn.commit();
return record;
} catch (error) {
await conn.rollback();
if (error.code === 'ER_LOCK_WAIT_TIMEOUT') {
log('error', 'Lock wait timeout exceeded, retrying...');
if (attempt >= retries - 1)
throw new Error('No se pudo obtener el registro después de múltiples intentos.');
await new Promise(resolve => setTimeout(resolve, delay));
} else {
log('error', 'Error al obtener y marcar el registro para procesamiento:', error);
return;
}
} finally {
conn.release();
return;
}
const record = rows[0];
await updateState(conn, record.expeditionFk, 12)
await conn.commit();
return record;
} catch (error) {
await conn.rollback();
log('error', 'Error al obtener y marcar el registro para procesamiento:', error);
return;
} finally {
conn.release();
}
}
async function processRecord(record) {
const conn = await getConn();
try {
await conn.beginTransaction();
log('debug', `(${record.expeditionFk}) Procesando...`);
const zplData = generateZPL(record, label);
@ -147,12 +135,10 @@ async function processRecord(record) {
log('error', `(${record.expeditionFk}) Error en la impresión`);
}
parentPort.postMessage('done');
await conn.commit();
} catch (error) {
log('error', `Error al procesar el registro ${error}`);
await updateState(conn, record.expeditionFk, 13)
parentPort.postMessage('error');
await conn.rollback();
} finally {
conn.release();
}
@ -175,7 +161,7 @@ parentPort.on('message', async msg => {
else {
setTimeout(async() => {
parentPort.postMessage('done');
}, 5000);
}, Number(env.GET_RECORD_DELAY));
}
} else
processRecord(msg).catch(err => log('error', 'Error en el worker:', err));