jerkjs 2.5.8 → 2.6.1
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/CHANGELOG.md +162 -99
- package/README.md +113 -190
- package/RESULTADOS_WAF.md +63 -0
- package/doc-2.5/MANUAL_MODULOS_ADMIN.md +287 -0
- package/doc-2.5/QUEUE_CLI_MODULE_MANUAL.md +289 -0
- package/doc-2.5/QUEUE_SYSTEM_MANUAL.md +320 -0
- package/doc-2.5/ROUTE_CACHE_MODULE_MANUAL.md +205 -0
- package/doc-2.5/WAF_MODULE_MANUAL.md +229 -0
- package/index.js +12 -3
- package/jerk-admin-client/README.md +69 -0
- package/jerk-admin-client/package.json +23 -0
- package/jerk-admin-client.js +257 -0
- package/lib/admin/AdminExtension.js +74 -19
- package/lib/admin/modules/ControllerGeneratorModule.js +414 -0
- package/lib/admin/modules/QueueManagementModule.js +265 -0
- package/lib/admin/modules/RouteCacheModule.js +227 -0
- package/lib/admin/modules/RouteManagerModule.js +468 -0
- package/lib/admin/modules/STATS_MODULE_README.md +15 -0
- package/lib/admin/modules/ViewCacheStatsModule.js +92 -0
- package/lib/admin/modules/WAFModule.js +737 -0
- package/lib/core/server.js +72 -69
- package/lib/middleware/firewall.js +112 -17
- package/lib/mvc/viewEngine.js +69 -10
- package/lib/queue/GlobalQueueStorage.js +38 -0
- package/lib/queue/QueueSystem.js +451 -0
- package/lib/queue/admin_example.js +114 -0
- package/lib/queue/example.js +268 -0
- package/lib/queue/integration.js +109 -0
- package/lib/utils/globalViewCacheInfo.js +16 -0
- package/lib/utils/globalWAFStats.js +54 -0
- package/package.json +2 -2
- package/test-colors.js +46 -0
- package/test-help-alias.js +31 -0
- package/ESTADISTICAS_RENDIMIENTO.md +0 -106
- package/debug_hook.js +0 -11
- package/docs/CACHE_SYSTEM_MAP.md +0 -206
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ejemplo de uso del sistema de colas para el framework JERK
|
|
3
|
+
* Archivo de ejemplo: queue/example.js
|
|
4
|
+
* Demostración con 3 colas distintas
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Importar el sistema de colas
|
|
8
|
+
const QueueIntegration = require('./integration');
|
|
9
|
+
const { hooks } = require('../../index.js'); // Suponiendo que se está usando dentro del framework
|
|
10
|
+
|
|
11
|
+
// Crear una instancia de la integración de colas
|
|
12
|
+
const queueIntegration = new QueueIntegration();
|
|
13
|
+
const queueSystem = queueIntegration.getQueueSystem();
|
|
14
|
+
|
|
15
|
+
// Ejemplo de tarea para la cola de procesamiento de imágenes
|
|
16
|
+
function tareaProcesamientoImagen(datos, taskObj) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
console.log(`[IMAGEN] Procesando imagen: ${datos.nombreArchivo}`);
|
|
19
|
+
|
|
20
|
+
// Simular un proceso de procesamiento de imagen
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
if (Math.random() < 0.2) { // 20% de probabilidad de fallo
|
|
23
|
+
console.error(`[IMAGEN] Falló el procesamiento de: ${datos.nombreArchivo}`);
|
|
24
|
+
reject(new Error(`Error procesando imagen: ${datos.nombreArchivo}`));
|
|
25
|
+
} else {
|
|
26
|
+
console.log(`[IMAGEN] Imagen procesada exitosamente: ${datos.nombreArchivo}`);
|
|
27
|
+
resolve(`Imagen ${datos.nombreArchivo} procesada con éxito`);
|
|
28
|
+
}
|
|
29
|
+
}, 2000);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Ejemplo de tarea para la cola de envío de correos
|
|
34
|
+
function tareaEnvioCorreo(datos, taskObj) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
console.log(`[CORREO] Enviando correo a: ${datos.destinatario}`);
|
|
37
|
+
|
|
38
|
+
// Simular un proceso de envío de correo
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
if (Math.random() < 0.15) { // 15% de probabilidad de fallo
|
|
41
|
+
console.error(`[CORREO] Falló el envío a: ${datos.destinatario}`);
|
|
42
|
+
reject(new Error(`Error enviando correo a: ${datos.destinatario}`));
|
|
43
|
+
} else {
|
|
44
|
+
console.log(`[CORREO] Correo enviado exitosamente a: ${datos.destinatario}`);
|
|
45
|
+
resolve(`Correo enviado a ${datos.destinatario} con éxito`);
|
|
46
|
+
}
|
|
47
|
+
}, 1500);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Ejemplo de tarea para la cola de procesamiento de pagos
|
|
52
|
+
function tareaProcesamientoPago(datos, taskObj) {
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
console.log(`[PAGO] Procesando pago de: $${datos.monto} para ${datos.usuario}`);
|
|
55
|
+
|
|
56
|
+
// Simular un proceso de procesamiento de pago
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
if (Math.random() < 0.25) { // 25% de probabilidad de fallo
|
|
59
|
+
console.error(`[PAGO] Falló el procesamiento de pago para: ${datos.usuario}`);
|
|
60
|
+
reject(new Error(`Error procesando pago para: ${datos.usuario}`));
|
|
61
|
+
} else {
|
|
62
|
+
console.log(`[PAGO] Pago procesado exitosamente para: ${datos.usuario}`);
|
|
63
|
+
resolve(`Pago de $${datos.monto} para ${datos.usuario} procesado con éxito`);
|
|
64
|
+
}
|
|
65
|
+
}, 3000);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Configurar la cola de procesamiento de imágenes con hooks personalizados
|
|
70
|
+
function setupColaImagenes() {
|
|
71
|
+
const HookSystem = require('../../lib/core/hooks');
|
|
72
|
+
const imagenHooks = new HookSystem();
|
|
73
|
+
|
|
74
|
+
// Hook para personalizar la lógica de procesamiento de tareas de imagen
|
|
75
|
+
imagenHooks.addAction('queue_execute_task', (task, queueName, taskObj) => {
|
|
76
|
+
console.log(`[IMAGEN] Preparando para procesar tarea de imagen: ${taskObj.id}`);
|
|
77
|
+
// Aquí puedes modificar la tarea o agregar lógica personalizada
|
|
78
|
+
const wrappedTask = async (datos, taskObj) => {
|
|
79
|
+
console.log(`[IMAGEN] Iniciando ejecución de tarea de imagen: ${taskObj.id} con datos:`, datos);
|
|
80
|
+
try {
|
|
81
|
+
const result = await task(datos, taskObj);
|
|
82
|
+
console.log(`[IMAGEN] Tarea de imagen completada: ${taskObj.id}`);
|
|
83
|
+
return result;
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.log(`[IMAGEN] Error en tarea de imagen: ${taskObj.id} - ${error.message}`);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
return wrappedTask;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Hook para manejar la lógica de fallback para tareas de imagen
|
|
93
|
+
imagenHooks.addAction('queue_task_fallback', (queueName, task, error) => {
|
|
94
|
+
console.log(`[IMAGEN] Ejecutando lógica de fallback para tarea de imagen:`, error.message);
|
|
95
|
+
// Aquí puedes implementar la lógica de fallback personalizada para imágenes
|
|
96
|
+
console.log(`[IMAGEN] Guardando información de error para procesamiento posterior...`);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Crear la cola de imágenes con los hooks personalizados
|
|
100
|
+
queueIntegration.createQueue('imagenes', {
|
|
101
|
+
concurrency: 3,
|
|
102
|
+
retryAttempts: 2,
|
|
103
|
+
retryDelay: 1000
|
|
104
|
+
}, imagenHooks);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Configurar la cola de envío de correos con hooks personalizados
|
|
108
|
+
function setupColaCorreos() {
|
|
109
|
+
const HookSystem = require('../../lib/core/hooks');
|
|
110
|
+
const correoHooks = new HookSystem();
|
|
111
|
+
|
|
112
|
+
// Hook para personalizar la lógica de procesamiento de tareas de correo
|
|
113
|
+
correoHooks.addAction('queue_execute_task', (task, queueName, taskObj) => {
|
|
114
|
+
console.log(`[CORREO] Preparando para enviar correo: ${taskObj.id}`);
|
|
115
|
+
// Aquí puedes modificar la tarea o agregar lógica personalizada
|
|
116
|
+
const wrappedTask = async (datos, taskObj) => {
|
|
117
|
+
console.log(`[CORREO] Iniciando ejecución de tarea de correo: ${taskObj.id} con datos:`, datos);
|
|
118
|
+
try {
|
|
119
|
+
const result = await task(datos, taskObj);
|
|
120
|
+
console.log(`[CORREO] Tarea de correo completada: ${taskObj.id}`);
|
|
121
|
+
return result;
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.log(`[CORREO] Error en tarea de correo: ${taskObj.id} - ${error.message}`);
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
return wrappedTask;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Hook para manejar la lógica de fallback para tareas de correo
|
|
131
|
+
correoHooks.addAction('queue_task_fallback', (queueName, task, error) => {
|
|
132
|
+
console.log(`[CORREO] Ejecutando lógica de fallback para tarea de correo:`, error.message);
|
|
133
|
+
// Aquí puedes implementar la lógica de fallback personalizada para correos
|
|
134
|
+
console.log(`[CORREO] Agregando destinatario a lista de reintento...`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Crear la cola de correos con los hooks personalizados
|
|
138
|
+
queueIntegration.createQueue('correos', {
|
|
139
|
+
concurrency: 2,
|
|
140
|
+
retryAttempts: 3,
|
|
141
|
+
retryDelay: 2000
|
|
142
|
+
}, correoHooks);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Configurar la cola de procesamiento de pagos con hooks personalizados
|
|
146
|
+
function setupColaPagos() {
|
|
147
|
+
const HookSystem = require('../../lib/core/hooks');
|
|
148
|
+
const pagoHooks = new HookSystem();
|
|
149
|
+
|
|
150
|
+
// Hook para personalizar la lógica de procesamiento de tareas de pago
|
|
151
|
+
pagoHooks.addAction('queue_execute_task', (task, queueName, taskObj) => {
|
|
152
|
+
console.log(`[PAGO] Preparando para procesar pago: ${taskObj.id}`);
|
|
153
|
+
// Aquí puedes modificar la tarea o agregar lógica personalizada
|
|
154
|
+
const wrappedTask = async (datos, taskObj) => {
|
|
155
|
+
console.log(`[PAGO] Iniciando ejecución de tarea de pago: ${taskObj.id} con datos:`, datos);
|
|
156
|
+
try {
|
|
157
|
+
const result = await task(datos, taskObj);
|
|
158
|
+
console.log(`[PAGO] Tarea de pago completada: ${taskObj.id}`);
|
|
159
|
+
return result;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.log(`[PAGO] Error en tarea de pago: ${taskObj.id} - ${error.message}`);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
return wrappedTask;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Hook para manejar la lógica de fallback para tareas de pago
|
|
169
|
+
pagoHooks.addAction('queue_task_fallback', (queueName, task, error) => {
|
|
170
|
+
console.log(`[PAGO] Ejecutando lógica de fallback para tarea de pago:`, error.message);
|
|
171
|
+
// Aquí puedes implementar la lógica de fallback personalizada para pagos
|
|
172
|
+
console.log(`[PAGO] Marcando transacción como pendiente para revisión manual...`);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Crear la cola de pagos con los hooks personalizados
|
|
176
|
+
queueIntegration.createQueue('pagos', {
|
|
177
|
+
concurrency: 1,
|
|
178
|
+
retryAttempts: 5,
|
|
179
|
+
retryDelay: 3000
|
|
180
|
+
}, pagoHooks);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Ejemplo de uso con 3 colas distintas
|
|
184
|
+
function ejemploDeUso() {
|
|
185
|
+
// Configurar las 3 colas con sus hooks personalizados
|
|
186
|
+
setupColaImagenes();
|
|
187
|
+
setupColaCorreos();
|
|
188
|
+
setupColaPagos();
|
|
189
|
+
|
|
190
|
+
// Agregar tareas a la cola de imágenes
|
|
191
|
+
console.log("\nAgregando tareas a la cola de imágenes...");
|
|
192
|
+
for (let i = 0; i < 5; i++) {
|
|
193
|
+
const taskId = queueIntegration.addTask('imagenes', tareaProcesamientoImagen, {
|
|
194
|
+
id: i,
|
|
195
|
+
nombreArchivo: `imagen_${i}.jpg`,
|
|
196
|
+
tamano: `${Math.floor(Math.random() * 10) + 1}MB`
|
|
197
|
+
}, i); // Usar el índice como prioridad (0 es la más alta)
|
|
198
|
+
|
|
199
|
+
console.log(`Tarea de imagen agregada con ID: ${taskId}`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Agregar tareas a la cola de correos
|
|
203
|
+
console.log("\nAgregando tareas a la cola de correos...");
|
|
204
|
+
const destinatarios = ['juan@ejemplo.com', 'maria@ejemplo.com', 'pedro@ejemplo.com', 'ana@ejemplo.com', 'luis@ejemplo.com'];
|
|
205
|
+
for (let i = 0; i < destinatarios.length; i++) {
|
|
206
|
+
const taskId = queueIntegration.addTask('correos', tareaEnvioCorreo, {
|
|
207
|
+
id: i,
|
|
208
|
+
destinatario: destinatarios[i],
|
|
209
|
+
asunto: `Mensaje de prueba #${i}`
|
|
210
|
+
}, i);
|
|
211
|
+
|
|
212
|
+
console.log(`Tarea de correo agregada con ID: ${taskId}`);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Agregar tareas a la cola de pagos
|
|
216
|
+
console.log("\nAgregando tareas a la cola de pagos...");
|
|
217
|
+
const usuarios = ['Cliente A', 'Cliente B', 'Cliente C', 'Cliente D', 'Cliente E'];
|
|
218
|
+
for (let i = 0; i < usuarios.length; i++) {
|
|
219
|
+
const taskId = queueIntegration.addTask('pagos', tareaProcesamientoPago, {
|
|
220
|
+
id: i,
|
|
221
|
+
usuario: usuarios[i],
|
|
222
|
+
monto: (Math.floor(Math.random() * 1000) + 100),
|
|
223
|
+
metodo: i % 2 === 0 ? 'Tarjeta' : 'PayPal'
|
|
224
|
+
}, i);
|
|
225
|
+
|
|
226
|
+
console.log(`Tarea de pago agregada con ID: ${taskId}`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Iniciar el procesamiento de tareas
|
|
230
|
+
console.log("\nIniciando el sistema de colas...");
|
|
231
|
+
queueIntegration.start();
|
|
232
|
+
|
|
233
|
+
// Mostrar estado periódicamente
|
|
234
|
+
setInterval(() => {
|
|
235
|
+
console.log('\n--- Estado del sistema de colas ---');
|
|
236
|
+
const status = queueIntegration.getStatus();
|
|
237
|
+
for (const [queueName, queueStatus] of Object.entries(status)) {
|
|
238
|
+
console.log(`${queueName}: Pendientes=${queueStatus.pendingTasks}, En proceso=${queueStatus.runningTasks}, Fallidas=${queueStatus.failedTasks}`);
|
|
239
|
+
}
|
|
240
|
+
console.log('------------------------------------\n');
|
|
241
|
+
}, 5000);
|
|
242
|
+
|
|
243
|
+
// Detener el sistema después de 60 segundos
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
console.log("\nDeteniendo el sistema de colas...");
|
|
246
|
+
queueIntegration.stop();
|
|
247
|
+
console.log('Sistema de colas detenido');
|
|
248
|
+
|
|
249
|
+
// Mostrar estado final
|
|
250
|
+
console.log('\n--- Estado final del sistema de colas ---');
|
|
251
|
+
const finalStatus = queueIntegration.getStatus();
|
|
252
|
+
for (const [queueName, queueStatus] of Object.entries(finalStatus)) {
|
|
253
|
+
console.log(`${queueName}: Pendientes=${queueStatus.pendingTasks}, En proceso=${queueStatus.runningTasks}, Fallidas=${queueStatus.failedTasks}`);
|
|
254
|
+
}
|
|
255
|
+
console.log('------------------------------------------\n');
|
|
256
|
+
}, 60000);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Exportar para que pueda ser usado en otros lugares
|
|
260
|
+
module.exports = {
|
|
261
|
+
QueueIntegration,
|
|
262
|
+
ejemploDeUso
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// Si este archivo se ejecuta directamente, correr el ejemplo
|
|
266
|
+
if (require.main === module) {
|
|
267
|
+
ejemploDeUso();
|
|
268
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integración del Sistema de Colas para el framework JERK
|
|
3
|
+
* Implementación del componente queue/integration.js
|
|
4
|
+
* Archivo de integración para usar el sistema de colas como extensión del framework
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { queueSystem } = require('./GlobalQueueStorage');
|
|
8
|
+
|
|
9
|
+
class QueueIntegration {
|
|
10
|
+
/**
|
|
11
|
+
* Constructor de la integración
|
|
12
|
+
* @param {Object} options - Opciones de configuración
|
|
13
|
+
*/
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
// Usar el sistema de colas global
|
|
16
|
+
this.queueSystem = queueSystem;
|
|
17
|
+
|
|
18
|
+
// Obtener los hooks del framework
|
|
19
|
+
try {
|
|
20
|
+
const framework = require('../../index.js');
|
|
21
|
+
this.globalHooks = framework.hooks;
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// Si no está disponible, crear instancia local
|
|
24
|
+
const HookSystem = require('../core/hooks');
|
|
25
|
+
this.globalHooks = new HookSystem();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Inicializa la integración con el framework
|
|
31
|
+
* @param {Object} frameworkInstance - Instancia del framework JERK
|
|
32
|
+
*/
|
|
33
|
+
initialize(frameworkInstance) {
|
|
34
|
+
// Registrar el sistema de colas en la instancia del framework
|
|
35
|
+
frameworkInstance.queueSystem = this.queueSystem;
|
|
36
|
+
|
|
37
|
+
// Disparar hook cuando se inicializa la integración
|
|
38
|
+
this.globalHooks.doAction('queue_integration_initialized', this.queueSystem);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Obtiene el sistema de colas
|
|
43
|
+
* @returns {QueueSystem} - Instancia del sistema de colas
|
|
44
|
+
*/
|
|
45
|
+
getQueueSystem() {
|
|
46
|
+
return this.queueSystem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Crea una cola específica con hooks personalizados
|
|
51
|
+
* @param {string} queueName - Nombre de la cola
|
|
52
|
+
* @param {Object} options - Opciones específicas para la cola
|
|
53
|
+
* @param {Object} hooks - Sistema de hooks específico para esta cola (opcional)
|
|
54
|
+
* @returns {Object} - Cola creada
|
|
55
|
+
*/
|
|
56
|
+
createQueue(queueName, options = {}, hooks = null) {
|
|
57
|
+
// Si se proporcionan hooks específicos para esta cola, usarlos
|
|
58
|
+
if (hooks) {
|
|
59
|
+
options.hooks = hooks;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Crear la cola con las opciones
|
|
63
|
+
return this.queueSystem.getOrCreateQueue(queueName, options);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Agrega una tarea a una cola
|
|
68
|
+
* @param {string} queueName - Nombre de la cola
|
|
69
|
+
* @param {Function} task - Función que representa la tarea
|
|
70
|
+
* @param {Object} data - Datos para la tarea
|
|
71
|
+
* @param {number} priority - Prioridad de la tarea
|
|
72
|
+
* @returns {string} - ID único de la tarea
|
|
73
|
+
*/
|
|
74
|
+
addTask(queueName, task, data = {}, priority = 0) {
|
|
75
|
+
return this.queueSystem.addTask(queueName, task, data, priority);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Inicia la ejecución de tareas en todas las colas
|
|
80
|
+
*/
|
|
81
|
+
start() {
|
|
82
|
+
this.queueSystem.start();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Detiene la ejecución de tareas en todas las colas
|
|
87
|
+
*/
|
|
88
|
+
stop() {
|
|
89
|
+
this.queueSystem.stop();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Obtiene el estado actual del sistema de colas
|
|
94
|
+
* @returns {Object} - Estado del sistema de colas
|
|
95
|
+
*/
|
|
96
|
+
getStatus() {
|
|
97
|
+
return this.queueSystem.getStatus();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Reintenta todas las tareas fallidas en una cola específica
|
|
102
|
+
* @param {string} queueName - Nombre de la cola
|
|
103
|
+
*/
|
|
104
|
+
retryFailedTasks(queueName) {
|
|
105
|
+
this.queueSystem.retryFailedTasks(queueName);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = QueueIntegration;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Almacenamiento global de información del caché de vistas para el framework JERK
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Crear un objeto global para almacenar información del caché de vistas
|
|
6
|
+
const globalViewCacheInfo = {
|
|
7
|
+
viewCache: new Map(), // Cache de vistas compiladas
|
|
8
|
+
cacheStats: {
|
|
9
|
+
hits: 0,
|
|
10
|
+
misses: 0,
|
|
11
|
+
totalViews: 0
|
|
12
|
+
},
|
|
13
|
+
viewDependencies: new Map() // Registro de dependencias entre vistas (inclusiones)
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = { globalViewCacheInfo };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sistema de Almacenamiento Global de Estadísticas del WAF (Web Application Firewall)
|
|
3
|
+
* Almacenamiento centralizado de datos del firewall para acceso eficiente
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Objeto global para almacenar estadísticas del WAF
|
|
7
|
+
const globalWAFStats = {
|
|
8
|
+
// Contadores de solicitudes
|
|
9
|
+
requestsProcessed: 0,
|
|
10
|
+
responsesSent: 0,
|
|
11
|
+
|
|
12
|
+
// Contadores de bytes
|
|
13
|
+
requestBytes: 0,
|
|
14
|
+
responseBytes: 0,
|
|
15
|
+
|
|
16
|
+
// Registro de accesos a rutas
|
|
17
|
+
routeAccesses: new Map(), // Mapa de rutas y número de accesos
|
|
18
|
+
|
|
19
|
+
// Registro de hits a endpoints
|
|
20
|
+
endpointHits: new Map(), // Mapa de endpoints y número de hits
|
|
21
|
+
|
|
22
|
+
// IPs bloqueadas temporalmente
|
|
23
|
+
blockedIPs: new Map(), // Mapa de IPs bloqueadas con información de bloqueo
|
|
24
|
+
|
|
25
|
+
// IPs en lista blanca (nunca bloqueadas)
|
|
26
|
+
whitelist: new Set(),
|
|
27
|
+
|
|
28
|
+
// IPs en lista negra (siempre bloqueadas)
|
|
29
|
+
blacklist: new Set(),
|
|
30
|
+
|
|
31
|
+
// Reglas de seguridad activas
|
|
32
|
+
securityRules: new Map(), // Mapa de reglas de seguridad
|
|
33
|
+
|
|
34
|
+
// Reglas de headers X-
|
|
35
|
+
xHeaderRules: new Map(), // Mapa de reglas de headers X-
|
|
36
|
+
|
|
37
|
+
// Tipos de ataques detectados
|
|
38
|
+
attackTypes: new Set(), // Conjunto de tipos de ataques detectados
|
|
39
|
+
|
|
40
|
+
// Contador de intentos de ataque
|
|
41
|
+
attackAttempts: 0,
|
|
42
|
+
|
|
43
|
+
// Registros de seguridad
|
|
44
|
+
securityLogs: [],
|
|
45
|
+
|
|
46
|
+
// Estadísticas de rendimiento
|
|
47
|
+
performanceStats: {
|
|
48
|
+
startTime: new Date().toISOString(),
|
|
49
|
+
requestProcessingTime: 0,
|
|
50
|
+
averageResponseTime: 0
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
module.exports = { globalWAFStats };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jerkjs",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "JERK Framework v2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
|
+
"description": "JERK Framework v2.6.1 - A comprehensive framework for building secure and scalable APIs with frontend support, sessions, template engine, integration with qbuilderjs, complete MVC architecture with models, enhanced route loading from directory, improved model loading system, administration extension, queue management system, route cache management module, and fixed routing issues with static and parametrized routes",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "echo \"Error: no test specified\" && exit 1",
|
package/test-colors.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Script de prueba para verificar que los colores funcionan en el módulo de cache de rutas
|
|
5
|
+
* Este script simula la interacción con el módulo para verificar la visualización de comandos en color
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Simulación de socket para probar la funcionalidad de color
|
|
9
|
+
const mockSocket = {
|
|
10
|
+
data: '',
|
|
11
|
+
write: function(text) {
|
|
12
|
+
this.data += text;
|
|
13
|
+
// En un entorno real, esto escribiría en el socket
|
|
14
|
+
process.stdout.write(text);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Importar el módulo
|
|
19
|
+
const RouteCacheModule = require('./lib/admin/modules/RouteCacheModule');
|
|
20
|
+
|
|
21
|
+
// Crear una instancia simulada de adminExtension
|
|
22
|
+
const mockAdminExtension = {
|
|
23
|
+
frameworkInstance: {
|
|
24
|
+
routeMatcher: {
|
|
25
|
+
routeRegexCache: new Map([
|
|
26
|
+
['/users/:id', /^\/users\/([^\/]+?)$/],
|
|
27
|
+
['/posts/:slug', /^\/posts\/([^\/]+?)$/]
|
|
28
|
+
]),
|
|
29
|
+
exactRoutes: new Map([
|
|
30
|
+
['GET:/api/users', { handler: { name: 'getUserHandler' }, isStatic: false }],
|
|
31
|
+
['POST:/api/users', { handler: { name: 'createUserHandler' }, isStatic: false }]
|
|
32
|
+
]),
|
|
33
|
+
indexesValid: true
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Crear instancia del módulo
|
|
39
|
+
const routeCacheModule = new RouteCacheModule(mockAdminExtension);
|
|
40
|
+
|
|
41
|
+
console.log('Probando el módulo de cache de rutas con colores...\n');
|
|
42
|
+
|
|
43
|
+
// Probar el manejo de un comando desconocido para ver el mensaje con comandos en verde
|
|
44
|
+
routeCacheModule.handleCommand('comando-invalido', mockSocket);
|
|
45
|
+
|
|
46
|
+
console.log('\nFin de la prueba.');
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Script de prueba para verificar que el alias '?' funciona en el sistema de administración
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { APIServer } = require('./index.js');
|
|
8
|
+
|
|
9
|
+
// Crear instancia del servidor
|
|
10
|
+
const server = new APIServer({ port: 3001 }); // Usar un puerto diferente para evitar conflictos
|
|
11
|
+
|
|
12
|
+
// Agregar una ruta de ejemplo
|
|
13
|
+
server.addRoute('GET', '/', (req, res) => {
|
|
14
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
15
|
+
res.end('Hola Mundo!');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Inicializar la extensión de administración
|
|
19
|
+
server.initializeAdminExtension({
|
|
20
|
+
port: 9998, // Usar un puerto diferente para evitar conflictos
|
|
21
|
+
host: '127.0.0.1'
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log('Servidor de prueba iniciado en http://localhost:3001');
|
|
25
|
+
console.log('Servidor de administración en tcp://localhost:9998');
|
|
26
|
+
console.log('\nPara probar el alias "?":');
|
|
27
|
+
console.log('- Conéctate al servidor de administración con: telnet localhost 9998 o nc localhost 9998');
|
|
28
|
+
console.log('- Escribe "?" y presiona Enter para ver la ayuda');
|
|
29
|
+
|
|
30
|
+
// Iniciar el servidor
|
|
31
|
+
server.start();
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# Informe de Pruebas del Módulo de Estadísticas - JERK Framework v2.5.8
|
|
2
|
-
|
|
3
|
-
## Resumen Ejecutivo
|
|
4
|
-
|
|
5
|
-
El módulo de estadísticas para la extensión de administración de JERK Framework ha sido sometido a pruebas exhaustivas que demuestran su capacidad para capturar y mostrar métricas precisas del servidor en tiempo real. Las pruebas incluyeron desde operaciones básicas hasta pruebas de estrés con 20,000 solicitudes concurrentes.
|
|
6
|
-
|
|
7
|
-
## Características del Módulo de Estadísticas
|
|
8
|
-
|
|
9
|
-
### Funcionalidades Implementadas
|
|
10
|
-
1. **Cantidad de requests procesados mostrando kilobytes**
|
|
11
|
-
2. **Cantidad de responses enviadas mostrando kilobytes**
|
|
12
|
-
3. **Accesos a las rutas registradas (input y output)**
|
|
13
|
-
4. **Endpoints y rutas más accedidas**
|
|
14
|
-
|
|
15
|
-
### Comandos Disponibles
|
|
16
|
-
- `stats` o `statistics`: Muestra estadísticas generales del servidor
|
|
17
|
-
- `requests`: Muestra estadísticas específicas de solicitudes
|
|
18
|
-
- `endpoints`: Muestra estadísticas de endpoints y rutas más accedidas
|
|
19
|
-
|
|
20
|
-
## Pruebas Realizadas
|
|
21
|
-
|
|
22
|
-
### 1. Pruebas Básicas
|
|
23
|
-
- Login con usuario testuser: ✅ Exitoso
|
|
24
|
-
- Consumo de endpoints con autenticación: ✅ Exitoso
|
|
25
|
-
- Uso del endpoint qwen con cola asincrónica: ✅ Exitoso
|
|
26
|
-
|
|
27
|
-
### 2. Pruebas con Apache Bench (ab)
|
|
28
|
-
- 100 solicitudes concurrentes a 10 por vez: ✅ Exitoso
|
|
29
|
-
- 50 solicitudes concurrentes al endpoint de resultados qwen: ✅ Exitoso
|
|
30
|
-
- 500 solicitudes concurrentes a 20 por vez: ✅ Exitoso
|
|
31
|
-
- 1000 solicitudes concurrentes a 50 por vez: ✅ Exitoso
|
|
32
|
-
- **20,000 solicitudes concurrentes a 100 por vez**: ✅ Exitoso
|
|
33
|
-
|
|
34
|
-
### 3. Pruebas de Rendimiento
|
|
35
|
-
- **Rendimiento Máximo**: 1,235.46 RPS (requests por segundo)
|
|
36
|
-
- **Tiempo Total de Prueba**: 16.188 segundos para 20,000 solicitudes
|
|
37
|
-
- **Conexiones Concurrentes**: 100
|
|
38
|
-
- **Tasa de Éxito**: 100% (0 fallos)
|
|
39
|
-
|
|
40
|
-
## Resultados de las Pruebas
|
|
41
|
-
|
|
42
|
-
### Estadísticas Generales (Después de 20,000 solicitudes)
|
|
43
|
-
- **Solicitudes procesadas**: 21,666
|
|
44
|
-
- **Solicitudes procesadas (KB)**: 740 Bytes
|
|
45
|
-
- **Respuestas enviadas**: 21,666
|
|
46
|
-
- **Respuestas enviadas (KB)**: 287.69 MB
|
|
47
|
-
- **Rutas registradas**: 45
|
|
48
|
-
- **Rutas activas**: 10
|
|
49
|
-
|
|
50
|
-
### Distribución de Accesos
|
|
51
|
-
- **GET /api/endpoints**: 20,602 accesos (dominante por la prueba de estrés)
|
|
52
|
-
- **GET /api/qwen/result/:id**: 1,051 accesos
|
|
53
|
-
- **POST /api/qwen/queue**: 3 accesos
|
|
54
|
-
- **POST /api/analytics**: 3 accesos
|
|
55
|
-
- **Otros endpoints**: variados accesos
|
|
56
|
-
|
|
57
|
-
### Métricas de Rendimiento
|
|
58
|
-
- **Transfer rate**: 17,911.75 KB/s recibidos
|
|
59
|
-
- **Tiempo medio por solicitud**: 80.942 ms
|
|
60
|
-
- **Tiempo de procesamiento**: 15-272 ms (rango)
|
|
61
|
-
- **50% de solicitudes**: respondidas en ≤75 ms
|
|
62
|
-
- **99% de solicitudes**: respondidas en ≤172 ms
|
|
63
|
-
|
|
64
|
-
## Validación de Requisitos
|
|
65
|
-
|
|
66
|
-
### ✅ Cantidad de requests procesados mostrando kilobytes
|
|
67
|
-
- Contador preciso de solicitudes: 21,666
|
|
68
|
-
- Medición de bytes recibidos: 740 Bytes
|
|
69
|
-
|
|
70
|
-
### ✅ Cantidad de responses enviadas mostrando kilobytes
|
|
71
|
-
- Contador preciso de respuestas: 21,666
|
|
72
|
-
- Medición de bytes enviados: 287.69 MB
|
|
73
|
-
|
|
74
|
-
### ✅ Accesos a las rutas registradas (input y output)
|
|
75
|
-
- Registro detallado de todas las rutas accedidas
|
|
76
|
-
- Visualización clara de accesos por método y ruta
|
|
77
|
-
|
|
78
|
-
### ✅ Endpoints y rutas más accedidas
|
|
79
|
-
- Visualización de endpoints más accedidos (top 10)
|
|
80
|
-
- Visualización de rutas más accedidas (top 10)
|
|
81
|
-
- Actualización en tiempo real
|
|
82
|
-
|
|
83
|
-
## Arquitectura del Sistema de Estadísticas
|
|
84
|
-
|
|
85
|
-
### Componentes Principales
|
|
86
|
-
1. **`globalStats`**: Sistema de almacenamiento global en `lib/utils/globalStats.js`
|
|
87
|
-
2. **Actualización directa**: Las estadísticas se actualizan en el servidor cuando ocurren eventos
|
|
88
|
-
3. **Módulo StatsModule**: Lee las estadísticas globales y las muestra a través de comandos
|
|
89
|
-
|
|
90
|
-
### Ventajas del Diseño
|
|
91
|
-
- **Acceso directo**: Sin dependencia de hooks para actualización
|
|
92
|
-
- **Confiable**: Persistencia de datos entre solicitudes
|
|
93
|
-
- **Rápido**: Bajo overhead de procesamiento
|
|
94
|
-
- **Escalable**: Funciona eficientemente bajo alta carga
|
|
95
|
-
|
|
96
|
-
## Conclusiones
|
|
97
|
-
|
|
98
|
-
El módulo de estadísticas para JERK Framework v2.5.8 ha demostrado un rendimiento excepcional bajo condiciones de estrés extremo. Las pruebas con 20,000 solicitudes concurrentes han confirmado que:
|
|
99
|
-
|
|
100
|
-
1. **Estabilidad**: 0 fallos en 20,000 solicitudes
|
|
101
|
-
2. **Precisión**: Métricas actualizadas correctamente en tiempo real
|
|
102
|
-
3. **Rendimiento**: Más de 1,200 RPS consistentes
|
|
103
|
-
4. **Escalabilidad**: Capacidad para manejar alta concurrencia
|
|
104
|
-
5. **Funcionalidad**: Cumplimiento completo de todos los requisitos
|
|
105
|
-
|
|
106
|
-
El módulo está listo para producción y proporciona una herramienta invaluable para el monitoreo y análisis del rendimiento del servidor.
|
package/debug_hook.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Modificar temporalmente el archivo de hooks para mostrar la estructura completa del objeto
|
|
2
|
-
const { hooks } = require('../index.js');
|
|
3
|
-
|
|
4
|
-
// Hook para registrar cada ruta encontrada - versión de depuración
|
|
5
|
-
hooks.addAction('route_matched', (matchedRoute, req, res) => {
|
|
6
|
-
console.log(`[${new Date().toISOString()}] DEBUG route_matched:`);
|
|
7
|
-
console.log(` matchedRoute:`, JSON.stringify(matchedRoute, null, 2));
|
|
8
|
-
console.log(` req.method:`, req ? req.method : 'undefined');
|
|
9
|
-
console.log(` req.url:`, req ? req.url : 'undefined');
|
|
10
|
-
console.log('---');
|
|
11
|
-
});
|