diff --git a/README.md b/README.md index c78ecad..ed7fca8 100644 --- a/README.md +++ b/README.md @@ -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. \ No newline at end of file diff --git a/worker/worker.js b/worker/worker.js index 8dd83f3..eadc589 100644 --- a/worker/worker.js +++ b/worker/worker.js @@ -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));