feat: refs #4452 vn changes
This commit is contained in:
parent
afcb079407
commit
cfa9b068ca
52
README.md
52
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.
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue