@onlineapps/service-wrapper 2.0.29 → 2.0.31
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/package.json +1 -1
- package/src/ServiceWrapper.js +47 -60
package/package.json
CHANGED
package/src/ServiceWrapper.js
CHANGED
|
@@ -137,14 +137,16 @@ class ServiceWrapper {
|
|
|
137
137
|
* @async
|
|
138
138
|
*/
|
|
139
139
|
async initialize() {
|
|
140
|
-
|
|
141
|
-
console
|
|
140
|
+
if (this.isInitialized) {
|
|
141
|
+
// Logger might not be initialized yet, use console as fallback
|
|
142
|
+
(this.logger || console).warn('ServiceWrapper already initialized');
|
|
142
143
|
return;
|
|
143
144
|
}
|
|
144
145
|
|
|
145
146
|
try {
|
|
146
147
|
const serviceName = this.config.service?.name || 'unnamed-service';
|
|
147
|
-
console
|
|
148
|
+
// Logger might not be initialized yet, use console as fallback
|
|
149
|
+
(this.logger || console).info(`Initializing ServiceWrapper for ${serviceName}`);
|
|
148
150
|
|
|
149
151
|
// 1. Initialize monitoring first (needed for logging)
|
|
150
152
|
if (this.config.wrapper?.monitoring?.enabled !== false) {
|
|
@@ -190,10 +192,15 @@ class ServiceWrapper {
|
|
|
190
192
|
}
|
|
191
193
|
|
|
192
194
|
this.isInitialized = true;
|
|
193
|
-
|
|
195
|
+
this.logger?.info(`ServiceWrapper initialized successfully for ${serviceName}`);
|
|
194
196
|
|
|
195
197
|
} catch (error) {
|
|
196
|
-
|
|
198
|
+
// Always log errors - use logger if available, otherwise console
|
|
199
|
+
if (this.logger) {
|
|
200
|
+
this.logger.error('Failed to initialize ServiceWrapper', { error: error.message, stack: error.stack });
|
|
201
|
+
} else {
|
|
202
|
+
console.error('Failed to initialize ServiceWrapper:', error);
|
|
203
|
+
}
|
|
197
204
|
throw error;
|
|
198
205
|
}
|
|
199
206
|
}
|
|
@@ -212,7 +219,8 @@ class ServiceWrapper {
|
|
|
212
219
|
});
|
|
213
220
|
|
|
214
221
|
this.logger = this.monitoring;
|
|
215
|
-
|
|
222
|
+
// Logger is now available, use it
|
|
223
|
+
this.logger.info('Monitoring connector initialized');
|
|
216
224
|
|
|
217
225
|
// Add monitoring middleware to Express app
|
|
218
226
|
if (this.app) {
|
|
@@ -257,32 +265,11 @@ class ServiceWrapper {
|
|
|
257
265
|
});
|
|
258
266
|
|
|
259
267
|
await this.mqClient.connect();
|
|
260
|
-
|
|
268
|
+
this.logger?.info('MQ connector initialized');
|
|
261
269
|
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
if (this.config.wrapper?.mq?.initInfrastructureQueues !== false) {
|
|
266
|
-
try {
|
|
267
|
-
const { initInfrastructureQueues } = require('@onlineapps/conn-infra-mq').utils || {};
|
|
268
|
-
if (initInfrastructureQueues) {
|
|
269
|
-
// Get channel from transport (RabbitMQClient has channel getter)
|
|
270
|
-
const channel = this.mqClient._transport?.channel || this.mqClient._transport?._channel;
|
|
271
|
-
if (channel) {
|
|
272
|
-
await initInfrastructureQueues(channel, {
|
|
273
|
-
logger: this.logger || console
|
|
274
|
-
});
|
|
275
|
-
console.log('✓ Infrastructure queues initialized');
|
|
276
|
-
} else {
|
|
277
|
-
console.warn('⚠ Could not get channel from MQ transport');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
} catch (error) {
|
|
281
|
-
// If tool not available or fails, log warning but continue
|
|
282
|
-
// Infrastructure queues may have been created by other services
|
|
283
|
-
console.warn('⚠ Could not initialize infrastructure queues:', error.message);
|
|
284
|
-
}
|
|
285
|
-
}
|
|
270
|
+
// NOTE: Business services (ServiceWrapper) do NOT create infrastructure queues
|
|
271
|
+
// Infrastructure queues are created by infrastructure services (Monitoring Consumer, Gateway)
|
|
272
|
+
// Business services only consume from them - if they don't exist, that's an infrastructure problem
|
|
286
273
|
}
|
|
287
274
|
|
|
288
275
|
/**
|
|
@@ -311,7 +298,7 @@ class ServiceWrapper {
|
|
|
311
298
|
|
|
312
299
|
// Initialize registry client connection
|
|
313
300
|
await this.registryClient.init();
|
|
314
|
-
|
|
301
|
+
this.logger?.info('Registry client initialized');
|
|
315
302
|
|
|
316
303
|
// Register service
|
|
317
304
|
const serviceInfo = {
|
|
@@ -329,28 +316,28 @@ class ServiceWrapper {
|
|
|
329
316
|
|
|
330
317
|
try {
|
|
331
318
|
const registrationResult = await this.registryClient.register(serviceInfo);
|
|
332
|
-
|
|
319
|
+
this.logger?.info(`Service registered: ${serviceName}`, { registrationResult });
|
|
333
320
|
|
|
334
321
|
// Store certificate if received
|
|
335
322
|
if (registrationResult.certificate) {
|
|
336
323
|
this.certificate = registrationResult.certificate;
|
|
337
|
-
|
|
324
|
+
this.logger?.info(`✓ Certificate received: ${registrationResult.certificate.certificateId}`);
|
|
338
325
|
}
|
|
339
326
|
|
|
340
327
|
// CRITICAL: Start workflow listeners ONLY after successful validation and registration with certificate
|
|
341
328
|
// Both workflow.init and service-specific listeners start here
|
|
342
329
|
if (registrationResult.success && registrationResult.certificate) {
|
|
343
|
-
|
|
330
|
+
this.logger?.info('✓ Certificate validated, starting workflow listeners...');
|
|
344
331
|
// Start workflow.init listener (for all services)
|
|
345
332
|
await this._startWorkflowInitListener();
|
|
346
333
|
// Start service-specific workflow listener
|
|
347
334
|
await this._startServiceWorkflowListener();
|
|
348
335
|
} else {
|
|
349
|
-
|
|
336
|
+
this.logger?.warn('⚠ Registration succeeded but no certificate received - workflow listeners NOT started');
|
|
350
337
|
}
|
|
351
338
|
|
|
352
339
|
} catch (error) {
|
|
353
|
-
|
|
340
|
+
this.logger?.error(`Service registration failed: ${error.message}`, { error: error.message, stack: error.stack });
|
|
354
341
|
throw new Error(`Failed to register service ${serviceName}: ${error.message}`);
|
|
355
342
|
}
|
|
356
343
|
|
|
@@ -359,13 +346,13 @@ class ServiceWrapper {
|
|
|
359
346
|
const heartbeatInterval = parseInt(process.env.HEARTBEAT_INTERVAL) ||
|
|
360
347
|
this.config.wrapper?.registry?.heartbeatInterval ||
|
|
361
348
|
10000;
|
|
362
|
-
|
|
349
|
+
this.logger?.info(`[ServiceWrapper] Heartbeat interval set to ${heartbeatInterval}ms`);
|
|
363
350
|
|
|
364
351
|
this.heartbeatTimer = setInterval(async () => {
|
|
365
352
|
try {
|
|
366
353
|
await this.registryClient.sendHeartbeat(serviceName);
|
|
367
354
|
} catch (error) {
|
|
368
|
-
|
|
355
|
+
this.logger?.error('Heartbeat failed', { error: error.message, stack: error.stack });
|
|
369
356
|
}
|
|
370
357
|
}, heartbeatInterval);
|
|
371
358
|
}
|
|
@@ -377,7 +364,7 @@ class ServiceWrapper {
|
|
|
377
364
|
async _initializeCache() {
|
|
378
365
|
const cacheUrl = this.config.wrapper?.cache?.url;
|
|
379
366
|
if (!cacheUrl) {
|
|
380
|
-
|
|
367
|
+
this.logger?.warn('Cache enabled but no URL provided. Skipping cache initialization');
|
|
381
368
|
return;
|
|
382
369
|
}
|
|
383
370
|
|
|
@@ -390,7 +377,7 @@ class ServiceWrapper {
|
|
|
390
377
|
});
|
|
391
378
|
|
|
392
379
|
await this.cacheConnector.connect();
|
|
393
|
-
|
|
380
|
+
this.logger?.info('Cache connector initialized');
|
|
394
381
|
}
|
|
395
382
|
|
|
396
383
|
/**
|
|
@@ -425,7 +412,7 @@ class ServiceWrapper {
|
|
|
425
412
|
res.json(health);
|
|
426
413
|
});
|
|
427
414
|
|
|
428
|
-
|
|
415
|
+
this.logger?.info(`Health check endpoint registered at ${healthEndpoint}`);
|
|
429
416
|
}
|
|
430
417
|
|
|
431
418
|
/**
|
|
@@ -476,7 +463,7 @@ class ServiceWrapper {
|
|
|
476
463
|
defaultTimeout: this.config.wrapper?.timeout || 30000
|
|
477
464
|
});
|
|
478
465
|
|
|
479
|
-
|
|
466
|
+
this.logger?.info('Orchestrator initialized');
|
|
480
467
|
}
|
|
481
468
|
|
|
482
469
|
/**
|
|
@@ -486,7 +473,7 @@ class ServiceWrapper {
|
|
|
486
473
|
*/
|
|
487
474
|
async _startWorkflowInitListener() {
|
|
488
475
|
if (!this.mqClient) {
|
|
489
|
-
|
|
476
|
+
this.logger?.warn('Cannot start workflow.init listener: MQ client not initialized');
|
|
490
477
|
return;
|
|
491
478
|
}
|
|
492
479
|
|
|
@@ -495,7 +482,7 @@ class ServiceWrapper {
|
|
|
495
482
|
await this._processWorkflowMessage(message, 'workflow.init');
|
|
496
483
|
});
|
|
497
484
|
|
|
498
|
-
|
|
485
|
+
this.logger?.info('✓ workflow.init listener started (after successful registration)');
|
|
499
486
|
}
|
|
500
487
|
|
|
501
488
|
/**
|
|
@@ -504,7 +491,7 @@ class ServiceWrapper {
|
|
|
504
491
|
*/
|
|
505
492
|
async _startServiceWorkflowListener() {
|
|
506
493
|
if (!this.mqClient) {
|
|
507
|
-
|
|
494
|
+
this.logger?.warn('Cannot start service workflow listener: MQ client not initialized');
|
|
508
495
|
return;
|
|
509
496
|
}
|
|
510
497
|
|
|
@@ -516,7 +503,7 @@ class ServiceWrapper {
|
|
|
516
503
|
await this._processWorkflowMessage(message, serviceQueue);
|
|
517
504
|
});
|
|
518
505
|
|
|
519
|
-
|
|
506
|
+
this.logger?.info(`✓ Service-specific workflow listener started: ${serviceQueue}`);
|
|
520
507
|
}
|
|
521
508
|
|
|
522
509
|
/**
|
|
@@ -541,7 +528,7 @@ class ServiceWrapper {
|
|
|
541
528
|
const isTest = flags.includes('test');
|
|
542
529
|
const isTier2Validation = flags.includes('tier2-validation');
|
|
543
530
|
|
|
544
|
-
|
|
531
|
+
this.logger?.debug(`Processing message from ${queueName}`, {
|
|
545
532
|
workflow_id: message.workflow_id,
|
|
546
533
|
step: message.step?.operation || message.operation,
|
|
547
534
|
flags,
|
|
@@ -551,7 +538,7 @@ class ServiceWrapper {
|
|
|
551
538
|
// Check if this message is for our service
|
|
552
539
|
const serviceName = this.config.service?.name || 'unnamed-service';
|
|
553
540
|
if (message.step?.service && message.step.service !== serviceName) {
|
|
554
|
-
|
|
541
|
+
this.logger?.debug(`Message not for this service (target: ${message.step.service})`);
|
|
555
542
|
return;
|
|
556
543
|
}
|
|
557
544
|
|
|
@@ -656,7 +643,7 @@ class ServiceWrapper {
|
|
|
656
643
|
const url = `http://localhost:${servicePort}${operation.endpoint}`;
|
|
657
644
|
const method = operation.method || 'POST';
|
|
658
645
|
|
|
659
|
-
|
|
646
|
+
this.logger?.debug(`Executing operation ${operationName} via ${method} ${url}`);
|
|
660
647
|
|
|
661
648
|
// Make HTTP request using fetch (Node.js 18+) or http module
|
|
662
649
|
const http = require('http');
|
|
@@ -711,7 +698,7 @@ class ServiceWrapper {
|
|
|
711
698
|
*/
|
|
712
699
|
async shutdown() {
|
|
713
700
|
const serviceName = this.config.service?.name || 'unnamed-service';
|
|
714
|
-
|
|
701
|
+
this.logger?.info(`Shutting down ServiceWrapper for ${serviceName}`);
|
|
715
702
|
|
|
716
703
|
try {
|
|
717
704
|
// Stop heartbeat
|
|
@@ -735,10 +722,10 @@ class ServiceWrapper {
|
|
|
735
722
|
}
|
|
736
723
|
|
|
737
724
|
this.isInitialized = false;
|
|
738
|
-
|
|
725
|
+
this.logger?.info('ServiceWrapper shutdown complete');
|
|
739
726
|
|
|
740
727
|
} catch (error) {
|
|
741
|
-
|
|
728
|
+
this.logger?.error('Error during shutdown', { error: error.message, stack: error.stack });
|
|
742
729
|
throw error;
|
|
743
730
|
}
|
|
744
731
|
}
|
|
@@ -756,7 +743,7 @@ class ServiceWrapper {
|
|
|
756
743
|
const proofPath = path.join(process.cwd(), '.validation-proof.json');
|
|
757
744
|
|
|
758
745
|
if (!fs.existsSync(proofPath)) {
|
|
759
|
-
|
|
746
|
+
this.logger?.warn('Validation proof not found', { proofPath });
|
|
760
747
|
return null;
|
|
761
748
|
}
|
|
762
749
|
|
|
@@ -765,15 +752,15 @@ class ServiceWrapper {
|
|
|
765
752
|
|
|
766
753
|
// Basic validation
|
|
767
754
|
if (!proof.validationProof || !proof.validationData) {
|
|
768
|
-
|
|
755
|
+
this.logger?.warn('Invalid validation proof format');
|
|
769
756
|
return null;
|
|
770
757
|
}
|
|
771
758
|
|
|
772
|
-
|
|
759
|
+
this.logger?.info('✓ Validation proof loaded', { proofHash: proof.validationProof.substring(0, 16) + '...' });
|
|
773
760
|
return proof;
|
|
774
761
|
|
|
775
762
|
} catch (error) {
|
|
776
|
-
|
|
763
|
+
this.logger?.warn('Failed to load validation proof', { error: error.message, stack: error.stack });
|
|
777
764
|
return null;
|
|
778
765
|
}
|
|
779
766
|
}
|
|
@@ -804,7 +791,7 @@ class ServiceWrapper {
|
|
|
804
791
|
// Build service URL for validation (HTTP calls to running server)
|
|
805
792
|
const serviceUrl = `http://localhost:${servicePort}`;
|
|
806
793
|
|
|
807
|
-
|
|
794
|
+
this.logger?.info('[ServiceWrapper] Checking validation proof...');
|
|
808
795
|
|
|
809
796
|
// Use injected orchestrator (for testing) or create new one (production)
|
|
810
797
|
const orchestrator = this._injectedValidationOrchestrator || new ValidationOrchestrator({
|
|
@@ -822,9 +809,9 @@ class ServiceWrapper {
|
|
|
822
809
|
}
|
|
823
810
|
|
|
824
811
|
if (result.skipped) {
|
|
825
|
-
|
|
812
|
+
this.logger?.info('[ServiceWrapper] ✓ Using existing validation proof');
|
|
826
813
|
} else {
|
|
827
|
-
|
|
814
|
+
this.logger?.info('[ServiceWrapper] ✓ Validation completed successfully');
|
|
828
815
|
}
|
|
829
816
|
|
|
830
817
|
// Store proof for registration
|