expressed-example-app 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -6
- package/app.js +106 -1
- package/controllers/mainController.js +63 -1
- package/controllers/productController.js +29 -1
- package/controllers/userController.js +29 -1
- package/package.json +28 -3
- package/queue-system.js +128 -0
- package/routes/queue-routes.json +44 -0
package/README.md
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
# Express-Router-BDS Example Application
|
|
2
2
|
|
|
3
|
-
This is a sample Express.js application demonstrating the usage of the `express-router-bds` routing system with custom hooks and
|
|
3
|
+
This is a sample Express.js application demonstrating the usage of the `express-router-bds` routing system with custom hooks, advanced features, and integrated queue system.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
7
|
This example application showcases:
|
|
8
8
|
|
|
9
|
-
- High-performance routing with `express-router-
|
|
9
|
+
- High-performance routing with `express-router-bds`
|
|
10
10
|
- JSON-based route configuration
|
|
11
11
|
- Custom hook system implementation
|
|
12
12
|
- Parameterized route handling
|
|
13
13
|
- Directory-based route loading
|
|
14
|
+
- Integrated queue system with `express-queued`
|
|
15
|
+
- Declarative route definitions in separate JSON files
|
|
14
16
|
|
|
15
17
|
## Features
|
|
16
18
|
|
|
17
19
|
- **Modular Route Configuration**: Routes defined in JSON files for easy maintenance
|
|
18
20
|
- **Custom Hooks**: Comprehensive hook system with `pre_route_load`, `post_route_load`, `before_route_handler`, `after_route_handler`, `route_handler_error`, and more
|
|
19
21
|
- **Parameterized Routes**: Support for dynamic routes like `/users/:id` and `/products/:category/:id`
|
|
22
|
+
- **Integrated Queue System**: Background task processing with `express-queued`
|
|
23
|
+
- **Declarative Routes**: Separate route files for different functionalities
|
|
20
24
|
- **Extensible Architecture**: Easy to extend with custom middleware and hooks
|
|
21
25
|
|
|
22
26
|
## Project Structure
|
|
@@ -24,26 +28,54 @@ This example application showcases:
|
|
|
24
28
|
```
|
|
25
29
|
express-app/
|
|
26
30
|
├── app.js # Main application entry point
|
|
31
|
+
├── queue-system.js # Queue system integration
|
|
27
32
|
├── hooks-config.js # Base hook configurations
|
|
28
33
|
├── hooks-personalizados.js # Custom hook implementations
|
|
29
34
|
├── controllers/
|
|
30
|
-
│ ├── mainController.js # Home and
|
|
35
|
+
│ ├── mainController.js # Home, init and queue route handlers
|
|
31
36
|
│ ├── productController.js # Product route handlers
|
|
32
37
|
│ └── userController.js # User route handlers
|
|
33
38
|
├── routes/
|
|
34
|
-
│
|
|
39
|
+
│ ├── main-routes.json # Main route definitions in JSON format
|
|
40
|
+
│ └── queue-routes.json # Queue-related route definitions
|
|
35
41
|
└── node_modules/
|
|
36
|
-
|
|
42
|
+
├── express-router-bds/ # Custom routing system
|
|
43
|
+
└── express-queued/ # Queue system
|
|
37
44
|
```
|
|
38
45
|
|
|
39
46
|
## Available Endpoints
|
|
40
47
|
|
|
48
|
+
### Main Endpoints
|
|
41
49
|
- `GET /` - Home page with welcome message
|
|
42
50
|
- `GET /init` - Initialization endpoint
|
|
43
51
|
- `GET /users/:id` - Get user by ID
|
|
44
52
|
- `GET /products/:category/:id` - Get product by category and ID
|
|
45
53
|
- `GET /test-hook` - Test endpoint for hook demonstration
|
|
46
54
|
|
|
55
|
+
### Queue System Endpoints
|
|
56
|
+
- `GET /queue-status` - Get the status of the queue system
|
|
57
|
+
- `GET /start-queues` - Start the queue system
|
|
58
|
+
- `GET /stop-queues` - Stop the queue system
|
|
59
|
+
- `POST /process-user` - Add a user processing task to the queue
|
|
60
|
+
- `POST /process-product` - Add a product processing task to the queue
|
|
61
|
+
- `POST /send-email` - Add an email sending task to the queue
|
|
62
|
+
|
|
63
|
+
## Queue System
|
|
64
|
+
|
|
65
|
+
The application integrates `express-queued` for background task processing:
|
|
66
|
+
|
|
67
|
+
- **Multiple Queues**: Dedicated queues for different types of tasks
|
|
68
|
+
- **Configurable Concurrency**: Control how many tasks execute simultaneously per queue
|
|
69
|
+
- **Retry System**: Automatic failure handling with configurable retries
|
|
70
|
+
- **Priority Management**: Assign priorities to tasks
|
|
71
|
+
- **Hooks Integration**: Customize processing with hooks
|
|
72
|
+
|
|
73
|
+
### Queue Types
|
|
74
|
+
- `procesamiento-general` - General processing tasks
|
|
75
|
+
- `envio-correos` - Email sending tasks
|
|
76
|
+
- `procesamiento-usuarios` - User processing tasks
|
|
77
|
+
- `procesamiento-productos` - Product processing tasks
|
|
78
|
+
|
|
47
79
|
## Hook System
|
|
48
80
|
|
|
49
81
|
The application demonstrates several types of hooks:
|
|
@@ -74,7 +106,7 @@ The application will be available at `http://localhost:3000`
|
|
|
74
106
|
|
|
75
107
|
## Testing
|
|
76
108
|
|
|
77
|
-
Test the endpoints:
|
|
109
|
+
Test the main endpoints:
|
|
78
110
|
|
|
79
111
|
```bash
|
|
80
112
|
curl http://localhost:3000
|
|
@@ -82,6 +114,23 @@ curl http://localhost:3000/users/123
|
|
|
82
114
|
curl http://localhost:3000/products/electronics/456
|
|
83
115
|
```
|
|
84
116
|
|
|
117
|
+
Test the queue system:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# Check queue status
|
|
121
|
+
curl http://localhost:3000/queue-status
|
|
122
|
+
|
|
123
|
+
# Add a user processing task
|
|
124
|
+
curl -X POST http://localhost:3000/process-user \
|
|
125
|
+
-H "Content-Type: application/json" \
|
|
126
|
+
-d '{"userId": "123", "name": "John Doe", "email": "john@example.com"}'
|
|
127
|
+
|
|
128
|
+
# Add an email sending task
|
|
129
|
+
curl -X POST http://localhost:3000/send-email \
|
|
130
|
+
-H "Content-Type: application/json" \
|
|
131
|
+
-d '{"to": "test@example.com", "subject": "Test", "content": "Test content"}'
|
|
132
|
+
```
|
|
133
|
+
|
|
85
134
|
## License
|
|
86
135
|
|
|
87
136
|
This project is part of the `express-router-bds` ecosystem and follows the same licensing terms.
|
package/app.js
CHANGED
|
@@ -3,6 +3,7 @@ const ExpressRouterIntegration = require('express-router-bds');
|
|
|
3
3
|
const RouteDirectoryLoader = require('express-router-bds/RouteDirectoryLoader');
|
|
4
4
|
const AppHooks = require('./hooks-config');
|
|
5
5
|
const HooksPersonalizados = require('./hooks-personalizados');
|
|
6
|
+
const QueueSystem = require('./queue-system');
|
|
6
7
|
|
|
7
8
|
const app = express();
|
|
8
9
|
const PORT = process.env.PORT || 3000;
|
|
@@ -10,16 +11,29 @@ const PORT = process.env.PORT || 3000;
|
|
|
10
11
|
// Crear instancia del router
|
|
11
12
|
const routerIntegration = new ExpressRouterIntegration();
|
|
12
13
|
|
|
14
|
+
// Crear instancia del sistema de colas
|
|
15
|
+
const queueSystem = new QueueSystem();
|
|
16
|
+
|
|
13
17
|
// Inicializar hooks y filtros
|
|
14
18
|
const appHooks = new AppHooks(app, routerIntegration.getHooks());
|
|
15
19
|
|
|
16
20
|
// Inicializar hooks personalizados
|
|
17
21
|
const hooksPersonalizados = new HooksPersonalizados(routerIntegration);
|
|
18
22
|
|
|
19
|
-
|
|
20
23
|
// Cargar rutas desde directorio
|
|
21
24
|
const routeDirectoryLoader = new RouteDirectoryLoader();
|
|
22
25
|
|
|
26
|
+
// Middleware para parsear JSON
|
|
27
|
+
app.use(express.json());
|
|
28
|
+
|
|
29
|
+
// Middleware para inyectar el sistema de colas en las solicitudes
|
|
30
|
+
app.use(queueSystem.getInstance().queueMiddleware());
|
|
31
|
+
|
|
32
|
+
// Middleware para inyectar el sistema de rutas en las solicitudes
|
|
33
|
+
app.use((req, res, next) => {
|
|
34
|
+
req.routerIntegration = routerIntegration;
|
|
35
|
+
next();
|
|
36
|
+
});
|
|
23
37
|
|
|
24
38
|
routerIntegration.addHook('route_matched', (matchedRoute, req, res) => {
|
|
25
39
|
console.log(`Ruta encontrada: ${matchedRoute.route.path}`);
|
|
@@ -41,6 +55,20 @@ routeDirectoryLoader.loadRoutesFromDirectory(routerIntegration, './routes')
|
|
|
41
55
|
console.error('Error cargando rutas desde directorio:', error.message);
|
|
42
56
|
});
|
|
43
57
|
|
|
58
|
+
// Cargar rutas específicas de colas
|
|
59
|
+
const RouteLoader = require('express-router-bds/RouteLoader');
|
|
60
|
+
const queueRouteLoader = new RouteLoader();
|
|
61
|
+
queueRouteLoader.loadRoutes(routerIntegration, './routes/queue-routes.json')
|
|
62
|
+
.then(queueRoutes => {
|
|
63
|
+
console.log(`${queueRoutes.length} rutas de colas cargadas`);
|
|
64
|
+
queueRoutes.forEach(route => {
|
|
65
|
+
console.log(`Ruta de cola cargada: ${route.method} ${route.path}`);
|
|
66
|
+
});
|
|
67
|
+
})
|
|
68
|
+
.catch(error => {
|
|
69
|
+
console.error('Error cargando rutas de colas:', error.message);
|
|
70
|
+
});
|
|
71
|
+
|
|
44
72
|
// Aplicar el router a la aplicación Express
|
|
45
73
|
routerIntegration.applyToApp(app);
|
|
46
74
|
|
|
@@ -49,6 +77,72 @@ app.use((req, res) => {
|
|
|
49
77
|
res.status(404).json({ error: 'Ruta no encontrada' });
|
|
50
78
|
});
|
|
51
79
|
|
|
80
|
+
// Ruta para obtener el estado del sistema de colas
|
|
81
|
+
app.get('/queue-status', (req, res) => {
|
|
82
|
+
const status = req.getQueueStatus();
|
|
83
|
+
res.json(status);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Ruta para iniciar el sistema de colas
|
|
87
|
+
app.get('/start-queues', (req, res) => {
|
|
88
|
+
queueSystem.start();
|
|
89
|
+
res.json({ message: 'Sistema de colas iniciado' });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Ruta para detener el sistema de colas
|
|
93
|
+
app.get('/stop-queues', (req, res) => {
|
|
94
|
+
queueSystem.stop();
|
|
95
|
+
res.json({ message: 'Sistema de colas detenido' });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Ruta para procesar un usuario en cola
|
|
99
|
+
app.post('/process-user', (req, res) => {
|
|
100
|
+
const { userId, name, email } = req.body;
|
|
101
|
+
|
|
102
|
+
if (!userId) {
|
|
103
|
+
return res.status(400).json({ error: 'userId es requerido' });
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const taskId = queueSystem.addUserProcessingTask({ userId, name, email });
|
|
107
|
+
|
|
108
|
+
res.json({
|
|
109
|
+
message: 'Tarea de procesamiento de usuario agregada a la cola',
|
|
110
|
+
taskId
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Ruta para procesar un producto en cola
|
|
115
|
+
app.post('/process-product', (req, res) => {
|
|
116
|
+
const { productId, name, price } = req.body;
|
|
117
|
+
|
|
118
|
+
if (!productId) {
|
|
119
|
+
return res.status(400).json({ error: 'productId es requerido' });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const taskId = queueSystem.addProductProcessingTask({ productId, name, price });
|
|
123
|
+
|
|
124
|
+
res.json({
|
|
125
|
+
message: 'Tarea de procesamiento de producto agregada a la cola',
|
|
126
|
+
taskId
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Ruta para enviar un correo en cola
|
|
131
|
+
app.post('/send-email', (req, res) => {
|
|
132
|
+
const { to, subject, content } = req.body;
|
|
133
|
+
|
|
134
|
+
if (!to) {
|
|
135
|
+
return res.status(400).json({ error: 'to es requerido' });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const taskId = queueSystem.addEmailSendingTask({ to, subject, content });
|
|
139
|
+
|
|
140
|
+
res.json({
|
|
141
|
+
message: 'Tarea de envío de correo agregada a la cola',
|
|
142
|
+
taskId
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
52
146
|
// Iniciar el servidor
|
|
53
147
|
app.listen(PORT, () => {
|
|
54
148
|
console.log(`Servidor corriendo en el puerto ${PORT}`);
|
|
@@ -57,6 +151,17 @@ app.listen(PORT, () => {
|
|
|
57
151
|
console.log('- GET /init');
|
|
58
152
|
console.log('- GET /users/:id');
|
|
59
153
|
console.log('- GET /products/:category/:id');
|
|
154
|
+
console.log('- GET /test-hook');
|
|
155
|
+
console.log('- GET /queue-status');
|
|
156
|
+
console.log('- GET /start-queues');
|
|
157
|
+
console.log('- GET /stop-queues');
|
|
158
|
+
console.log('- POST /process-user');
|
|
159
|
+
console.log('- POST /process-product');
|
|
160
|
+
console.log('- POST /send-email');
|
|
161
|
+
|
|
162
|
+
// Iniciar el sistema de colas
|
|
163
|
+
queueSystem.start();
|
|
164
|
+
console.log('Sistema de colas iniciado');
|
|
60
165
|
});
|
|
61
166
|
|
|
62
167
|
module.exports = app;
|
|
@@ -24,11 +24,73 @@ class MainController {
|
|
|
24
24
|
* @param {Object} res - Objeto de respuesta
|
|
25
25
|
*/
|
|
26
26
|
init(req, res) {
|
|
27
|
-
res.json({
|
|
27
|
+
res.json({
|
|
28
28
|
message: 'Aplicación inicializada correctamente con Router-BDS',
|
|
29
29
|
status: 'success'
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Obtiene el estado del sistema de colas
|
|
35
|
+
* @param {Object} req - Objeto de solicitud
|
|
36
|
+
* @param {Object} res - Objeto de respuesta
|
|
37
|
+
*/
|
|
38
|
+
getQueueStatus(req, res) {
|
|
39
|
+
const status = req.getQueueStatus();
|
|
40
|
+
res.json(status);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Inicia el sistema de colas
|
|
45
|
+
* @param {Object} req - Objeto de solicitud
|
|
46
|
+
* @param {Object} res - Objeto de respuesta
|
|
47
|
+
*/
|
|
48
|
+
startQueues(req, res) {
|
|
49
|
+
req.queueSystem.start();
|
|
50
|
+
res.json({ message: 'Sistema de colas iniciado' });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Detiene el sistema de colas
|
|
55
|
+
* @param {Object} req - Objeto de solicitud
|
|
56
|
+
* @param {Object} res - Objeto de respuesta
|
|
57
|
+
*/
|
|
58
|
+
stopQueues(req, res) {
|
|
59
|
+
req.queueSystem.stop();
|
|
60
|
+
res.json({ message: 'Sistema de colas detenido' });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Agrega una tarea de envío de correo a la cola
|
|
65
|
+
* @param {Object} req - Objeto de solicitud
|
|
66
|
+
* @param {Object} res - Objeto de respuesta
|
|
67
|
+
*/
|
|
68
|
+
sendEmailInQueue(req, res) {
|
|
69
|
+
const { to, subject, content } = req.body;
|
|
70
|
+
|
|
71
|
+
if (!to) {
|
|
72
|
+
return res.status(400).json({ error: 'to es requerido' });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const taskId = req.addTask('envio-correos', async (data, taskObj) => {
|
|
76
|
+
console.log(`[ENVIO-CORREO] Enviando correo a: ${data.to}`);
|
|
77
|
+
|
|
78
|
+
// Simular envío de correo (con 10% de probabilidad de fallo)
|
|
79
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
80
|
+
|
|
81
|
+
if (Math.random() < 0.1) {
|
|
82
|
+
throw new Error(`Fallo al enviar correo a: ${data.to}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
console.log(`[ENVIO-CORREO] Correo enviado exitosamente a: ${data.to}`);
|
|
86
|
+
return `Correo enviado a ${data.to} exitosamente`;
|
|
87
|
+
}, { to, subject, content });
|
|
88
|
+
|
|
89
|
+
res.json({
|
|
90
|
+
message: 'Tarea de envío de correo agregada a la cola',
|
|
91
|
+
taskId
|
|
92
|
+
});
|
|
93
|
+
}
|
|
32
94
|
}
|
|
33
95
|
|
|
34
96
|
module.exports = new MainController();
|
|
@@ -10,13 +10,41 @@ class ProductController {
|
|
|
10
10
|
getProduct(req, res) {
|
|
11
11
|
const category = req.params.category;
|
|
12
12
|
const productId = req.params.id;
|
|
13
|
-
res.json({
|
|
13
|
+
res.json({
|
|
14
14
|
message: `Obteniendo producto de la categoría "${category}" con ID: ${productId}`,
|
|
15
15
|
category: category,
|
|
16
16
|
productId: productId,
|
|
17
17
|
timestamp: new Date().toISOString()
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Procesa un producto en cola
|
|
23
|
+
* @param {Object} req - Objeto de solicitud
|
|
24
|
+
* @param {Object} res - Objeto de respuesta
|
|
25
|
+
*/
|
|
26
|
+
processProductInQueue(req, res) {
|
|
27
|
+
const { productId, name, price } = req.body;
|
|
28
|
+
|
|
29
|
+
if (!productId) {
|
|
30
|
+
return res.status(400).json({ error: 'productId es requerido' });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const taskId = req.addTask('procesamiento-productos', async (data, taskObj) => {
|
|
34
|
+
console.log(`[PROCESAMIENTO-PRODUCTO] Procesando producto:`, data.productId || data.id);
|
|
35
|
+
|
|
36
|
+
// Simular procesamiento
|
|
37
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
38
|
+
|
|
39
|
+
console.log(`[PROCESAMIENTO-PRODUCTO] Producto procesado exitosamente:`, data.productId || data.id);
|
|
40
|
+
return `Producto ${data.productId || data.id} procesado exitosamente`;
|
|
41
|
+
}, { productId, name, price });
|
|
42
|
+
|
|
43
|
+
res.json({
|
|
44
|
+
message: 'Tarea de procesamiento de producto agregada a la cola',
|
|
45
|
+
taskId
|
|
46
|
+
});
|
|
47
|
+
}
|
|
20
48
|
}
|
|
21
49
|
|
|
22
50
|
module.exports = new ProductController();
|
|
@@ -9,12 +9,40 @@ class UserController {
|
|
|
9
9
|
*/
|
|
10
10
|
getUser(req, res) {
|
|
11
11
|
const userId = req.params.id;
|
|
12
|
-
res.json({
|
|
12
|
+
res.json({
|
|
13
13
|
message: `Obteniendo información del usuario con ID: ${userId}`,
|
|
14
14
|
userId: userId,
|
|
15
15
|
timestamp: new Date().toISOString()
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Procesa un usuario en cola
|
|
21
|
+
* @param {Object} req - Objeto de solicitud
|
|
22
|
+
* @param {Object} res - Objeto de respuesta
|
|
23
|
+
*/
|
|
24
|
+
processUserInQueue(req, res) {
|
|
25
|
+
const { userId, name, email } = req.body;
|
|
26
|
+
|
|
27
|
+
if (!userId) {
|
|
28
|
+
return res.status(400).json({ error: 'userId es requerido' });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const taskId = req.addTask('procesamiento-usuarios', async (data, taskObj) => {
|
|
32
|
+
console.log(`[PROCESAMIENTO-USUARIO] Procesando usuario:`, data.userId || data.id);
|
|
33
|
+
|
|
34
|
+
// Simular procesamiento
|
|
35
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
36
|
+
|
|
37
|
+
console.log(`[PROCESAMIENTO-USUARIO] Usuario procesado exitosamente:`, data.userId || data.id);
|
|
38
|
+
return `Usuario ${data.userId || data.id} procesado exitosamente`;
|
|
39
|
+
}, { userId, name, email });
|
|
40
|
+
|
|
41
|
+
res.json({
|
|
42
|
+
message: 'Tarea de procesamiento de usuario agregada a la cola',
|
|
43
|
+
taskId
|
|
44
|
+
});
|
|
45
|
+
}
|
|
18
46
|
}
|
|
19
47
|
|
|
20
48
|
module.exports = new UserController();
|
package/package.json
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expressed-example-app",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "Advanced Express.js application featuring high-performance routing with custom hooks, declarative route definitions, and integrated queue system for background task processing. Perfect for scalable web applications requiring sophisticated routing and async job handling.",
|
|
5
5
|
"main": "app.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "node app.js",
|
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
9
9
|
},
|
|
10
|
-
"keywords": [
|
|
10
|
+
"keywords": [
|
|
11
|
+
"express",
|
|
12
|
+
"routing",
|
|
13
|
+
"router",
|
|
14
|
+
"middleware",
|
|
15
|
+
"api",
|
|
16
|
+
"rest",
|
|
17
|
+
"web-framework",
|
|
18
|
+
"backend",
|
|
19
|
+
"server",
|
|
20
|
+
"http",
|
|
21
|
+
"framework",
|
|
22
|
+
"nodejs",
|
|
23
|
+
"javascript",
|
|
24
|
+
"queues",
|
|
25
|
+
"async",
|
|
26
|
+
"asynchronous",
|
|
27
|
+
"tasks",
|
|
28
|
+
"jobs",
|
|
29
|
+
"background-jobs",
|
|
30
|
+
"hooks",
|
|
31
|
+
"extensible",
|
|
32
|
+
"modular",
|
|
33
|
+
"declarative-routing",
|
|
34
|
+
"web express example"
|
|
35
|
+
],
|
|
11
36
|
"author": "BDS",
|
|
12
37
|
"license": "ISC",
|
|
13
38
|
"dependencies": {
|
package/queue-system.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// queue-system.js
|
|
2
|
+
// Sistema de colas para la aplicación Express
|
|
3
|
+
|
|
4
|
+
const ExpressQueueIntegration = require('express-queued');
|
|
5
|
+
|
|
6
|
+
class QueueSystem {
|
|
7
|
+
constructor() {
|
|
8
|
+
// Crear instancia del sistema de colas
|
|
9
|
+
this.expressQueue = new ExpressQueueIntegration();
|
|
10
|
+
|
|
11
|
+
// Configurar las colas
|
|
12
|
+
this.setupQueues();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
setupQueues() {
|
|
16
|
+
// Cola para procesamiento general
|
|
17
|
+
this.expressQueue.createQueue('procesamiento-general', {
|
|
18
|
+
concurrency: 2,
|
|
19
|
+
retryAttempts: 3,
|
|
20
|
+
retryDelay: 1000
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Cola para envío de correos
|
|
24
|
+
this.expressQueue.createQueue('envio-correos', {
|
|
25
|
+
concurrency: 1,
|
|
26
|
+
retryAttempts: 5,
|
|
27
|
+
retryDelay: 2000
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Cola para procesamiento de usuarios
|
|
31
|
+
this.expressQueue.createQueue('procesamiento-usuarios', {
|
|
32
|
+
concurrency: 3,
|
|
33
|
+
retryAttempts: 2,
|
|
34
|
+
retryDelay: 1500
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Cola para procesamiento de productos
|
|
38
|
+
this.expressQueue.createQueue('procesamiento-productos', {
|
|
39
|
+
concurrency: 2,
|
|
40
|
+
retryAttempts: 3,
|
|
41
|
+
retryDelay: 1000
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Método para obtener la instancia del sistema de colas
|
|
46
|
+
getInstance() {
|
|
47
|
+
return this.expressQueue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Método para iniciar el sistema de colas
|
|
51
|
+
start() {
|
|
52
|
+
this.expressQueue.start();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Método para detener el sistema de colas
|
|
56
|
+
stop() {
|
|
57
|
+
this.expressQueue.stop();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Ejemplo de tarea para procesamiento de usuarios
|
|
61
|
+
addUserProcessingTask(userData) {
|
|
62
|
+
return this.expressQueue.addTask(
|
|
63
|
+
'procesamiento-usuarios',
|
|
64
|
+
this.processUser.bind(this),
|
|
65
|
+
userData,
|
|
66
|
+
0 // Prioridad alta
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Ejemplo de tarea para procesamiento de productos
|
|
71
|
+
addProductProcessingTask(productData) {
|
|
72
|
+
return this.expressQueue.addTask(
|
|
73
|
+
'procesamiento-productos',
|
|
74
|
+
this.processProduct.bind(this),
|
|
75
|
+
productData,
|
|
76
|
+
0 // Prioridad alta
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Ejemplo de tarea para envío de correos
|
|
81
|
+
addEmailSendingTask(emailData) {
|
|
82
|
+
return this.expressQueue.addTask(
|
|
83
|
+
'envio-correos',
|
|
84
|
+
this.sendEmail.bind(this),
|
|
85
|
+
emailData,
|
|
86
|
+
0 // Prioridad alta
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Función de ejemplo para procesamiento de usuarios
|
|
91
|
+
async processUser(data, taskObj) {
|
|
92
|
+
console.log(`[PROCESAMIENTO-USUARIO] Procesando usuario:`, data.userId || data.id);
|
|
93
|
+
|
|
94
|
+
// Simular procesamiento
|
|
95
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
96
|
+
|
|
97
|
+
console.log(`[PROCESAMIENTO-USUARIO] Usuario procesado exitosamente:`, data.userId || data.id);
|
|
98
|
+
return `Usuario ${data.userId || data.id} procesado exitosamente`;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Función de ejemplo para procesamiento de productos
|
|
102
|
+
async processProduct(data, taskObj) {
|
|
103
|
+
console.log(`[PROCESAMIENTO-PRODUCTO] Procesando producto:`, data.productId || data.id);
|
|
104
|
+
|
|
105
|
+
// Simular procesamiento
|
|
106
|
+
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
107
|
+
|
|
108
|
+
console.log(`[PROCESAMIENTO-PRODUCTO] Producto procesado exitosamente:`, data.productId || data.id);
|
|
109
|
+
return `Producto ${data.productId || data.id} procesado exitosamente`;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Función de ejemplo para envío de correos
|
|
113
|
+
async sendEmail(data, taskObj) {
|
|
114
|
+
console.log(`[ENVIO-CORREO] Enviando correo a:`, data.email || data.to);
|
|
115
|
+
|
|
116
|
+
// Simular envío de correo (con 10% de probabilidad de fallo)
|
|
117
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
118
|
+
|
|
119
|
+
if (Math.random() < 0.1) {
|
|
120
|
+
throw new Error(`Fallo al enviar correo a: ${data.email || data.to}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log(`[ENVIO-CORREO] Correo enviado exitosamente a:`, data.email || data.to);
|
|
124
|
+
return `Correo enviado a ${data.email || data.to} exitosamente`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = QueueSystem;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"method": "GET",
|
|
4
|
+
"path": "/queue-status",
|
|
5
|
+
"controller": "./controllers/mainController",
|
|
6
|
+
"handler": "getQueueStatus",
|
|
7
|
+
"contentType": "application/json"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"method": "GET",
|
|
11
|
+
"path": "/start-queues",
|
|
12
|
+
"controller": "./controllers/mainController",
|
|
13
|
+
"handler": "startQueues",
|
|
14
|
+
"contentType": "application/json"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"method": "GET",
|
|
18
|
+
"path": "/stop-queues",
|
|
19
|
+
"controller": "./controllers/mainController",
|
|
20
|
+
"handler": "stopQueues",
|
|
21
|
+
"contentType": "application/json"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"method": "POST",
|
|
25
|
+
"path": "/process-user",
|
|
26
|
+
"controller": "./controllers/userController",
|
|
27
|
+
"handler": "processUserInQueue",
|
|
28
|
+
"contentType": "application/json"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"method": "POST",
|
|
32
|
+
"path": "/process-product",
|
|
33
|
+
"controller": "./controllers/productController",
|
|
34
|
+
"handler": "processProductInQueue",
|
|
35
|
+
"contentType": "application/json"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"method": "POST",
|
|
39
|
+
"path": "/send-email",
|
|
40
|
+
"controller": "./controllers/mainController",
|
|
41
|
+
"handler": "sendEmailInQueue",
|
|
42
|
+
"contentType": "application/json"
|
|
43
|
+
}
|
|
44
|
+
]
|