kukuy 1.5.0 → 1.9.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.
Files changed (40) hide show
  1. package/README.md +159 -188
  2. package/balancer.log +30 -0
  3. package/certs/auto/certificate.crt +22 -0
  4. package/certs/auto/private.key +28 -0
  5. package/kukuy-plugins/README.md +125 -0
  6. package/kukuy-plugins/cache-plugin/index.js +477 -0
  7. package/kukuy-plugins/cache-plugin/manifest.json +17 -0
  8. package/kukuy-plugins/ejemplo-plugin/index.js +41 -0
  9. package/kukuy-plugins/ejemplo-plugin/manifest.json +11 -0
  10. package/kukuy-plugins/health-checker/index.js +168 -0
  11. package/kukuy-plugins/health-checker/manifest.json +16 -0
  12. package/kukuy-plugins/health-monitor/index.js +58 -0
  13. package/kukuy-plugins/health-monitor/manifest.json +16 -0
  14. package/kukuy-plugins/redirect-plugin/index.js +172 -0
  15. package/kukuy-plugins/redirect-plugin/manifest.json +15 -0
  16. package/package.json +7 -3
  17. package/servers_real.json +5 -0
  18. package/src/core/Balancer.js +176 -39
  19. package/src/core/ServerPool.js +2 -2
  20. package/src/extensibility/ExtendedFilterChain.js +90 -0
  21. package/src/extensibility/ExtendedHookManager.js +87 -0
  22. package/src/extensibility/FilterChain.js +2 -9
  23. package/src/extensibility/HookManager.js +1 -0
  24. package/src/extensibility/PostStartupExtension.js +97 -0
  25. package/src/plugins/PluginManager.js +231 -0
  26. package/src/utils/HealthChecker.js +61 -6
  27. package/.ctagsd/ctagsd.json +0 -954
  28. package/.ctagsd/file_list.txt +0 -100
  29. package/.ctagsd/tags.db +0 -0
  30. package/CHANGELOG.md +0 -125
  31. package/LICENSE +0 -680
  32. package/README-SSL.md +0 -165
  33. package/captura.png +0 -0
  34. package/kukuu1.webp +0 -0
  35. package/kukuy.workspace +0 -11
  36. package/optimize-mariadb.sh +0 -152
  37. package/restart-balancer.sh +0 -10
  38. package/scripts/load_test.py +0 -151
  39. package/stress-test.js +0 -190
  40. package/test_optimization.js +0 -54
@@ -18,8 +18,8 @@
18
18
 
19
19
  const fs = require('fs');
20
20
  const url = require('url');
21
- const { HookManager } = require('../extensibility/HookManager');
22
- const { FilterChain } = require('../extensibility/FilterChain');
21
+ const { ExtendedHookManager } = require('../extensibility/ExtendedHookManager');
22
+ const { ExtendedFilterChain } = require('../extensibility/ExtendedFilterChain');
23
23
  const { ServerPool } = require('./ServerPool');
24
24
  const { AlgorithmManager } = require('../algorithms/AlgorithmManager');
25
25
  const { ConfigManager } = require('../config/ConfigManager');
@@ -31,13 +31,15 @@ const { HttpsBalancer } = require('../protocol/HttpsBalancer');
31
31
  const { ProfessionalMetrics } = require('../utils/ProfessionalMetrics');
32
32
  const { WebDashboard } = require('../dashboard/WebDashboard');
33
33
  const { WebSocketServer } = require('../dashboard/WebSocketServer');
34
+ const { PostStartupExtension } = require('../extensibility/PostStartupExtension');
35
+ const { PluginManager } = require('../plugins/PluginManager');
34
36
 
35
37
  class Balancer {
36
38
  constructor() {
37
39
  this.config = ConfigManager.getInstance();
38
- this.hookManager = new HookManager();
39
- this.filterChain = new FilterChain();
40
- this.serverPool = new ServerPool();
40
+ this.hookManager = new ExtendedHookManager();
41
+ this.filterChain = new ExtendedFilterChain();
42
+ this.serverPool = new ServerPool(this);
41
43
  this.algorithmManager = new AlgorithmManager();
42
44
  this.routeLoader = new RouteLoader();
43
45
  this.logger = new Logger();
@@ -56,6 +58,64 @@ class Balancer {
56
58
 
57
59
  // Inicializar servidor WebSocket para datos en tiempo real
58
60
  this.webSocketServer = new WebSocketServer(this);
61
+
62
+ // Inicializar sistema de extensión post-inicio
63
+ this.postStartupExtension = new PostStartupExtension(this);
64
+
65
+ // Activar plugin de depuración si está habilitado
66
+ this.initializeDebugPlugin();
67
+
68
+ // Inicializar sistema de plugins
69
+ this.pluginManager = new PluginManager(this);
70
+ }
71
+
72
+ initializeDebugPlugin() {
73
+ // Verificar si el plugin de depuración está habilitado
74
+ const debugEnabled = process.env.DEBUG_REQUEST_HEADERS === 'true' ||
75
+ process.env.KUKUY_DEBUG_HEADERS === 'true';
76
+
77
+ if (debugEnabled) {
78
+ // Registrar hooks para mostrar encabezados y servidor de destino
79
+
80
+ // Hook para mostrar encabezados cuando se recibe una solicitud
81
+ this.hookManager.addHook('onRequestReceived', ({ req, res }) => {
82
+ console.log('\n--- Nueva Solicitud Recibida ---');
83
+ console.log(`Método: ${req.method}`);
84
+ console.log(`URL: ${req.url}`);
85
+ console.log('Encabezados:');
86
+
87
+ // Mostrar todos los encabezados de la solicitud
88
+ for (const [header, value] of Object.entries(req.headers)) {
89
+ console.log(` ${header}: ${value}`);
90
+ }
91
+
92
+ console.log('-----------------------------\n');
93
+ });
94
+
95
+ // Hook para mostrar el servidor de destino asignado
96
+ this.hookManager.addHook('onServerSelected', ({ req, res, server }) => {
97
+ console.log('\n--- Servidor de Destino Asignado ---');
98
+ console.log(`Solicitud: ${req.method} ${req.url}`);
99
+ console.log(`Servidor destino: ${server.url}`);
100
+ console.log(`ID del servidor: ${server.id}`);
101
+ console.log(`Protocolo: ${server.protocol}`);
102
+ console.log(`Host: ${server.host}`);
103
+ console.log(`Etiquetas: ${server.tags.join(', ') || 'ninguna'}`);
104
+ console.log('----------------------------------\n');
105
+ });
106
+
107
+ // Hook para mostrar información cuando se envía la respuesta
108
+ this.hookManager.addHook('onResponseSent', ({ req, res, serverRes, responseTime }) => {
109
+ console.log('\n--- Respuesta Enviada ---');
110
+ console.log(`Solicitud: ${req.method} ${req.url}`);
111
+ console.log(`Código de estado: ${serverRes.statusCode}`);
112
+ console.log(`Tiempo de respuesta: ${responseTime}ms`);
113
+ console.log('------------------------\n');
114
+ });
115
+
116
+ console.log('Plugin de depuración de solicitud activado');
117
+ console.log('Mostrando encabezados de solicitud y servidores de destino en stdout');
118
+ }
59
119
  }
60
120
 
61
121
  loadConfiguration() {
@@ -88,7 +148,7 @@ class Balancer {
88
148
  }
89
149
  }
90
150
 
91
- start() {
151
+ async start() {
92
152
  // Crear servidor HTTP usando HttpBalancer
93
153
  if (this.config.httpPort) {
94
154
  this.httpBalancer = new HttpBalancer(this.config.httpPort, this.handleRequest.bind(this));
@@ -112,13 +172,19 @@ class Balancer {
112
172
  // Iniciar servidor WebSocket para datos en tiempo real
113
173
  const wsPort = process.env.WEBSOCKET_PORT || 8083;
114
174
  this.webSocketServer.start(wsPort);
175
+
176
+ // Cargar plugins después de iniciar componentes principales
177
+ await this.pluginManager.loadPlugins();
178
+
179
+ // Imprimir información sobre los plugins disponibles y activos
180
+ this.pluginManager.printPluginsInfo();
115
181
  }
116
182
 
117
183
  async handleRequest(clientReq, clientRes) {
118
184
  try {
119
185
  // Aplicar filters antes de procesar la solicitud
120
186
  const filterData = { req: clientReq, res: clientRes, allowed: true, statusCode: 200, message: '' };
121
- const filteredResult = await this.filterChain.applyFilters('request', clientReq, clientRes);
187
+ const filteredResult = await this.filterChain.applyFilters('request_processing', clientReq, clientRes);
122
188
 
123
189
  if (!filteredResult || !filteredResult.allowed) {
124
190
  const statusCode = filteredResult?.statusCode || 403;
@@ -128,27 +194,16 @@ class Balancer {
128
194
  return;
129
195
  }
130
196
 
131
- // Emitir hook cuando se recibe una solicitud
132
- await this.hookManager.executeHooks('onRequestReceived', { req: clientReq, res: clientRes });
133
-
134
- // Determinar la ruta objetivo
135
- const targetServer = await this.getTargetServer(clientReq.url, clientReq.method, clientReq);
136
-
137
- if (!targetServer) {
138
- clientRes.writeHead(404);
139
- clientRes.end('No available servers');
197
+ // Verificar si el filtro indicó que la respuesta se sirvió desde caché
198
+ if (filteredResult?.cached && filteredResult?.cacheHit) {
199
+ // La respuesta ya fue enviada desde el filtro de caché, terminamos aquí
200
+ // No debemos continuar con ningún otro procesamiento
140
201
  return;
141
202
  }
142
203
 
143
- // Emitir hook después de seleccionar servidor
144
- await this.hookManager.executeHooks('onServerSelected', {
145
- req: clientReq,
146
- res: clientRes,
147
- server: targetServer
148
- });
149
-
150
- // Reenviar solicitud al servidor backend
151
- this.proxyRequest(clientReq, clientRes, targetServer);
204
+ // Si llegamos aquí, no hubo cache hit, continuar con el flujo normal
205
+ // y permitir que se ejecuten los hooks y se contacte al servidor backend
206
+ await this.processRequestNormally(clientReq, clientRes);
152
207
 
153
208
  } catch (error) {
154
209
  this.logger.error(`Error manejando solicitud: ${error.message}`);
@@ -165,6 +220,36 @@ class Balancer {
165
220
  }
166
221
  }
167
222
 
223
+ async processRequestNormally(clientReq, clientRes) {
224
+ // Emitir hook cuando se recibe una solicitud
225
+ await this.hookManager.executeHooks('onRequestReceived', { req: clientReq, res: clientRes });
226
+
227
+ // Determinar la ruta objetivo
228
+ const targetServer = await this.getTargetServer(clientReq.url, clientReq.method, clientReq);
229
+
230
+ if (!targetServer) {
231
+ clientRes.writeHead(404);
232
+ clientRes.end('No available servers');
233
+ return;
234
+ }
235
+
236
+ // Emitir hook después de seleccionar servidor
237
+ await this.hookManager.executeHooks('onServerSelected', {
238
+ req: clientReq,
239
+ res: clientRes,
240
+ server: targetServer
241
+ });
242
+
243
+ // Verificar si después de los hooks la respuesta ya fue enviada
244
+ // (esto cubre el caso de onServerError u otros hooks que puedan enviar respuesta desde la caché)
245
+ if (clientRes.headersSent) {
246
+ return;
247
+ }
248
+
249
+ // Reenviar solicitud al servidor backend
250
+ this.proxyRequest(clientReq, clientRes, targetServer);
251
+ }
252
+
168
253
  async getTargetServer(requestUrl, method, clientReq = null) {
169
254
  // Usar RouteLoader para encontrar la ruta coincidente
170
255
  const matchedRoute = this.routeLoader.findMatchingRoute(requestUrl, method);
@@ -220,12 +305,6 @@ class Balancer {
220
305
  clientReq.pipe(proxyReq);
221
306
 
222
307
  proxyReq.on('response', (serverRes) => {
223
- // Copiar headers de la respuesta
224
- clientRes.writeHead(serverRes.statusCode, serverRes.headers);
225
-
226
- // Enviar cuerpo de la respuesta al cliente
227
- serverRes.pipe(clientRes);
228
-
229
308
  // Calcular tiempo de respuesta
230
309
  const responseTime = Date.now() - startTime;
231
310
 
@@ -250,16 +329,66 @@ class Balancer {
250
329
  // Actualizar estado del servidor en las métricas
251
330
  this.metricsCollector.updateServerStatus(server.id, 'online');
252
331
 
253
- // Emitir hook cuando se envía la respuesta
254
- this.hookManager.executeHooks('onResponseSent', {
255
- req: clientReq,
256
- res: clientRes,
257
- serverRes,
258
- server,
259
- responseTime
332
+ // Capturar el cuerpo de la respuesta para posibles plugins
333
+ let responseData = [];
334
+
335
+ serverRes.on('data', (chunk) => {
336
+ responseData.push(chunk);
260
337
  });
261
338
 
262
- resolve(); // Resolver la promesa al completar la solicitud
339
+ serverRes.on('end', () => {
340
+ const responseBody = Buffer.concat(responseData);
341
+
342
+ // Emitir hook antes de enviar la respuesta al cliente
343
+ // Esto permite a los plugins interceptar la respuesta
344
+ this.hookManager.executeHooks('onResponseReady', {
345
+ req: clientReq,
346
+ res: clientRes,
347
+ serverRes,
348
+ responseBody,
349
+ server,
350
+ responseTime
351
+ }).then(() => {
352
+ // Si algún plugin ha manejado la respuesta, no la enviamos aquí
353
+ if (!clientRes.headersSent) {
354
+ // Copiar headers de la respuesta
355
+ clientRes.writeHead(serverRes.statusCode, serverRes.headers);
356
+
357
+ // Enviar cuerpo de la respuesta al cliente
358
+ clientRes.end(responseBody);
359
+ }
360
+
361
+ // Emitir hook cuando se envía la respuesta
362
+ this.hookManager.executeHooks('onResponseSent', {
363
+ req: clientReq,
364
+ res: clientRes,
365
+ serverRes,
366
+ server,
367
+ responseTime
368
+ });
369
+
370
+ resolve(); // Resolver la promesa al completar la solicitud
371
+ }).catch(err => {
372
+ console.error('Error ejecutando hook onResponseReady:', err);
373
+
374
+ // En caso de error, enviar la respuesta de todas formas
375
+ if (!clientRes.headersSent) {
376
+ clientRes.writeHead(serverRes.statusCode, serverRes.headers);
377
+ clientRes.end(responseBody);
378
+ }
379
+
380
+ // Emitir hook cuando se envía la respuesta
381
+ this.hookManager.executeHooks('onResponseSent', {
382
+ req: clientReq,
383
+ res: clientRes,
384
+ serverRes,
385
+ server,
386
+ responseTime
387
+ });
388
+
389
+ resolve(); // Resolver la promesa al completar la solicitud
390
+ });
391
+ });
263
392
  });
264
393
 
265
394
  proxyReq.on('error', async (err) => {
@@ -350,6 +479,14 @@ class Balancer {
350
479
  this.httpsBalancer.stop();
351
480
  }
352
481
  }
482
+
483
+ /**
484
+ * Get the post-startup extension API
485
+ * @returns {PostStartupExtension} The extension API
486
+ */
487
+ getPostStartupExtension() {
488
+ return this.postStartupExtension;
489
+ }
353
490
  }
354
491
 
355
492
  module.exports = { Balancer };
@@ -1,12 +1,12 @@
1
1
  const { HealthChecker } = require('../utils/HealthChecker');
2
2
 
3
3
  class ServerPool {
4
- constructor() {
4
+ constructor(balancer = null) {
5
5
  this.servers = [];
6
6
  this.healthyServers = []; // Caché de servidores saludables
7
7
  this.serversById = new Map(); // Acceso rápido por ID
8
8
  this.serversByTag = new Map(); // Caché de servidores por tag
9
- this.healthChecker = new HealthChecker();
9
+ this.healthChecker = new HealthChecker(balancer);
10
10
  this.nextId = 1;
11
11
  this.cacheValid = false; // Indicador de validez de caché
12
12
  }
@@ -0,0 +1,90 @@
1
+ const { FilterChain } = require('./FilterChain');
2
+
3
+ /**
4
+ * Extended FilterChain that allows registering filters after startup
5
+ */
6
+ class ExtendedFilterChain {
7
+ constructor() {
8
+ // Create a new instance of the original FilterChain
9
+ this.originalFilterChain = new FilterChain();
10
+
11
+ // Storage for post-startup filters
12
+ this.postStartupFilters = {
13
+ request_processing: [] // Using the same hook type as original
14
+ };
15
+ }
16
+
17
+ /**
18
+ * Register a filter after startup
19
+ * @param {string} type - Type of filter ('request_processing' for now)
20
+ * @param {Function} filterFunction - The filter function to register
21
+ * @param {number} priority - Priority of the filter (lower numbers execute first)
22
+ */
23
+ registerFilter(type, filterFunction, priority = 0) {
24
+ if (!this.postStartupFilters[type]) {
25
+ this.postStartupFilters[type] = [];
26
+ }
27
+
28
+ // Insert filter according to priority
29
+ const filterObj = {
30
+ fn: filterFunction,
31
+ priority,
32
+ id: this.generateId()
33
+ };
34
+
35
+ this.postStartupFilters[type].push(filterObj);
36
+ this.postStartupFilters[type].sort((a, b) => a.priority - b.priority);
37
+
38
+ // Also add to the original hook system
39
+ this.originalFilterChain.addFilter(type, filterFunction);
40
+
41
+ console.log(`Filter registered for ${type} with priority ${priority}`);
42
+ }
43
+
44
+ /**
45
+ * Unregister a specific filter
46
+ * @param {string} type - Type of filter
47
+ * @param {string} filterId - ID of the filter to remove
48
+ */
49
+ unregisterFilter(type, filterId) {
50
+ if (this.postStartupFilters[type]) {
51
+ this.postStartupFilters[type] = this.postStartupFilters[type].filter(f => f.id !== filterId);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Apply all filters of a specific type
57
+ * @param {string} type - Type of filter
58
+ * @param {Object} req - Request object
59
+ * @param {Object} res - Response object
60
+ * @param {Object} additionalData - Additional data to pass to filters
61
+ * @returns {Object} Result of filter processing
62
+ */
63
+ async applyFilters(type, req, res, additionalData = {}) {
64
+ // Apply filters using the original system which now includes post-startup filters
65
+ return await this.originalFilterChain.applyFilters(type, req, res, additionalData);
66
+ }
67
+
68
+ /**
69
+ * Generate a unique ID
70
+ * @returns {string} Unique identifier
71
+ */
72
+ generateId() {
73
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
74
+ }
75
+
76
+ // Proxy other methods to the original FilterChain
77
+ addFilter(filterName, filterFunction) {
78
+ this.originalFilterChain.addFilter(filterName, filterFunction);
79
+ }
80
+
81
+ applySpecificFilter(filterName, data) {
82
+ return this.originalFilterChain.applySpecificFilter(filterName, data);
83
+ }
84
+
85
+ getCacheStats() {
86
+ return this.originalFilterChain.getCacheStats();
87
+ }
88
+ }
89
+
90
+ module.exports = { ExtendedFilterChain };
@@ -0,0 +1,87 @@
1
+ const { HookManager } = require('./HookManager');
2
+
3
+ /**
4
+ * Extended HookManager that allows registering hooks after startup
5
+ */
6
+ class ExtendedHookManager {
7
+ constructor() {
8
+ // Create a new instance of the original HookManager
9
+ this.originalHookManager = new HookManager();
10
+
11
+ // Storage for post-startup hooks
12
+ this.postStartupHooks = {};
13
+ }
14
+
15
+ /**
16
+ * Register a hook after startup
17
+ * @param {string} hookName - Name of the hook
18
+ * @param {Function} callback - The callback function to register
19
+ * @param {number} priority - Priority of the hook (lower numbers execute first)
20
+ */
21
+ registerHook(hookName, callback, priority = 0) {
22
+ if (!this.postStartupHooks[hookName]) {
23
+ this.postStartupHooks[hookName] = [];
24
+ }
25
+
26
+ const hookObj = {
27
+ callback,
28
+ priority,
29
+ id: this.generateId()
30
+ };
31
+
32
+ this.postStartupHooks[hookName].push(hookObj);
33
+ this.postStartupHooks[hookName].sort((a, b) => a.priority - b.priority);
34
+
35
+ // Add to the original hook system
36
+ this.originalHookManager.addHook(hookName, callback);
37
+
38
+ console.log(`Hook registered: ${hookName} with priority ${priority}`);
39
+ }
40
+
41
+ /**
42
+ * Unregister a specific hook
43
+ * @param {string} hookName - Name of the hook
44
+ * @param {string} hookId - ID of the hook to remove
45
+ */
46
+ unregisterHook(hookName, hookId) {
47
+ if (this.postStartupHooks[hookName]) {
48
+ this.postStartupHooks[hookName] = this.postStartupHooks[hookName].filter(h => h.id !== hookId);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Execute all hooks for a specific event
54
+ * @param {string} hookName - Name of the hook
55
+ * @param {Object} data - Data to pass to the hooks
56
+ */
57
+ async executeHooks(hookName, data) {
58
+ // Execute hooks using the original system which now includes post-startup hooks
59
+ return await this.originalHookManager.executeHooks(hookName, data);
60
+ }
61
+
62
+ /**
63
+ * Generate a unique ID
64
+ * @returns {string} Unique identifier
65
+ */
66
+ generateId() {
67
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
68
+ }
69
+
70
+ // Proxy other methods to the original HookManager
71
+ addHook(hookName, callback) {
72
+ this.originalHookManager.addHook(hookName, callback);
73
+ }
74
+
75
+ executeHooks(hookName, data) {
76
+ return this.originalHookManager.executeHooks(hookName, data);
77
+ }
78
+
79
+ getRegisteredHooks() {
80
+ return Object.keys(this.postStartupHooks).reduce((acc, hookName) => {
81
+ acc[hookName] = this.postStartupHooks[hookName].length;
82
+ return acc;
83
+ }, {});
84
+ }
85
+ }
86
+
87
+ module.exports = { ExtendedHookManager };
@@ -35,14 +35,6 @@ class FilterChain {
35
35
  }
36
36
 
37
37
  async applyFilters(type, req, res, additionalData = {}) {
38
- // Verificar si la solicitud puede ser atendida desde caché
39
- const cacheResult = await this.cachingFilter.apply(req, res, additionalData);
40
-
41
- // Si fue un hit de caché, retornar inmediatamente
42
- if (cacheResult.cached && cacheResult.cacheHit) {
43
- return cacheResult;
44
- }
45
-
46
38
  // Usar el sistema de filtros de la librería para otros filtros
47
39
  // Creamos un objeto combinado para pasar al filtro
48
40
  const filterData = { req, res, ...additionalData, allowed: true, statusCode: 200, message: '' };
@@ -51,7 +43,8 @@ class FilterChain {
51
43
  const processedData = this.hooks.applyFilters('request_processing', filterData);
52
44
 
53
45
  // Devolver el resultado procesado
54
- return { ...processedData, ...cacheResult };
46
+ // Nota: El manejo de caché ahora se delega a los plugins registrados
47
+ return processedData;
55
48
  }
56
49
 
57
50
  // Filtro de autenticación básico
@@ -11,6 +11,7 @@ class HookManager {
11
11
  const hookNames = [
12
12
  'onRequestReceived',
13
13
  'onServerSelected',
14
+ 'onResponseReady',
14
15
  'onResponseSent',
15
16
  'onServerError'
16
17
  ];
@@ -0,0 +1,97 @@
1
+ /**
2
+ * API for registering extensions after Kukuy startup
3
+ */
4
+ class PostStartupExtension {
5
+ constructor(balancer) {
6
+ this.balancer = balancer;
7
+ }
8
+
9
+ /**
10
+ * Register a filter after startup
11
+ * @param {string} type - Type of filter ('request_processing' for now)
12
+ * @param {Function} filterFunction - The filter function to register
13
+ * @param {number} priority - Priority of the filter (lower numbers execute first)
14
+ */
15
+ registerFilter(type, filterFunction, priority = 0) {
16
+ if (this.balancer.filterChain && typeof this.balancer.filterChain.registerFilter === 'function') {
17
+ this.balancer.filterChain.registerFilter(type, filterFunction, priority);
18
+ } else {
19
+ console.error('FilterChain no disponible o registerFilter no es una función');
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Unregister a filter
25
+ * @param {string} type - Type of filter
26
+ * @param {string} filterId - ID of the filter to remove
27
+ */
28
+ unregisterFilter(type, filterId) {
29
+ if (this.balancer.filterChain && typeof this.balancer.filterChain.unregisterFilter === 'function') {
30
+ this.balancer.filterChain.unregisterFilter(type, filterId);
31
+ } else {
32
+ console.error('FilterChain no disponible o unregisterFilter no es una función');
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Register a hook after startup
38
+ * @param {string} hookName - Name of the hook
39
+ * @param {Function} callback - The callback function to register
40
+ * @param {number} priority - Priority of the hook (lower numbers execute first)
41
+ */
42
+ registerHook(hookName, callback, priority = 0) {
43
+ if (this.balancer.hookManager && typeof this.balancer.hookManager.registerHook === 'function') {
44
+ this.balancer.hookManager.registerHook(hookName, callback, priority);
45
+ } else {
46
+ console.error('HookManager no disponible o registerHook no es una función');
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Unregister a hook
52
+ * @param {string} hookName - Name of the hook
53
+ * @param {string} hookId - ID of the hook to remove
54
+ */
55
+ unregisterHook(hookName, hookId) {
56
+ if (this.balancer.hookManager && typeof this.balancer.hookManager.unregisterHook === 'function') {
57
+ this.balancer.hookManager.unregisterHook(hookName, hookId);
58
+ } else {
59
+ console.error('HookManager no disponible o unregisterHook no es una función');
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Get access to system components
65
+ * @param {string} componentName - Name of the component to access
66
+ * @returns {Object} The requested component or null
67
+ */
68
+ getComponent(componentName) {
69
+ switch(componentName) {
70
+ case 'serverPool':
71
+ return this.balancer.serverPool;
72
+ case 'algorithmManager':
73
+ return this.balancer.algorithmManager;
74
+ case 'metricsCollector':
75
+ return this.balancer.metricsCollector;
76
+ case 'config':
77
+ return this.balancer.config;
78
+ case 'routeLoader':
79
+ return this.balancer.routeLoader;
80
+ default:
81
+ return null;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get information about registered hooks
87
+ * @returns {Object} Information about registered hooks
88
+ */
89
+ getRegisteredHooks() {
90
+ if (this.balancer.hookManager && typeof this.balancer.hookManager.getRegisteredHooks === 'function') {
91
+ return this.balancer.hookManager.getRegisteredHooks();
92
+ }
93
+ return {};
94
+ }
95
+ }
96
+
97
+ module.exports = { PostStartupExtension };