@onlineapps/service-wrapper 2.0.47 → 2.0.49

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/service-wrapper",
3
- "version": "2.0.47",
3
+ "version": "2.0.49",
4
4
  "description": "Thin orchestration layer for microservices - delegates all infrastructure concerns to specialized connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -569,6 +569,39 @@ class ServiceWrapper {
569
569
 
570
570
  const serviceName = this.config.service?.name || 'unnamed-service';
571
571
 
572
+ // Health monitoring and channel close hooks configuration
573
+ const healthCheckConfig = {
574
+ healthCheckInterval: this.config.wrapper?.mq?.healthCheckInterval || 30000, // 30s
575
+ healthCheckEnabled: this.config.wrapper?.mq?.healthCheckEnabled !== false, // Default: true
576
+ criticalHealthShutdown: this.config.wrapper?.mq?.criticalHealthShutdown !== false, // Default: true
577
+ criticalHealthShutdownDelay: this.config.wrapper?.mq?.criticalHealthShutdownDelay || 60000, // 60s
578
+ // Health reporting callbacks
579
+ healthReportCallback: async (health) => {
580
+ if (this.monitoring && this.monitoring.info) {
581
+ this.monitoring.info('MQ Health Check', {
582
+ healthy: health.healthy,
583
+ issues: health.issues,
584
+ consumers: health.consumers,
585
+ queues: health.queues,
586
+ channels: health.channels
587
+ });
588
+ }
589
+ },
590
+ healthCriticalCallback: async (health) => {
591
+ if (this.monitoring && this.monitoring.error) {
592
+ this.monitoring.error('MQ CRITICAL HEALTH', {
593
+ issues: health.issues,
594
+ consumers: health.consumers,
595
+ queues: health.queues,
596
+ channels: health.channels,
597
+ timestamp: health.timestamp
598
+ });
599
+ }
600
+ // Also log to console for visibility
601
+ console.error('[ServiceWrapper] [MQ] CRITICAL HEALTH:', health.issues);
602
+ }
603
+ };
604
+
572
605
  this.mqClient = new MQConnector({
573
606
  type: 'rabbitmq',
574
607
  host: mqUrl,
@@ -578,12 +611,64 @@ class ServiceWrapper {
578
611
  prefetch: this.config.wrapper?.mq?.prefetch || 10,
579
612
  durable: true,
580
613
  noAck: false,
581
- logger: this.logger || console
614
+ logger: this.logger || console,
615
+ ...healthCheckConfig
582
616
  });
583
617
 
618
+ // Register channel close hooks AFTER mqClient is created but BEFORE connect
619
+ // Access the underlying transport (RabbitMQClient) to register hooks
620
+ // Note: transport is created during connect(), so we need to register hooks after connect
621
+ // We'll do this in a separate method called after connect
622
+
584
623
  try {
585
624
  await this.mqClient.connect();
586
625
  this.logger?.info('MQ connector initialized');
626
+
627
+ // Register channel close hooks after connection is established
628
+ // Access the underlying transport (RabbitMQClient) via _transport
629
+ if (this.mqClient._transport && typeof this.mqClient._transport.onChannelClose === 'function') {
630
+ // Register hook for all channel types
631
+ this.mqClient._transport.onChannelClose('all', (details) => {
632
+ const logData = {
633
+ type: details.type,
634
+ reason: details.reason,
635
+ error: details.error ? {
636
+ message: details.error.message,
637
+ code: details.error.code,
638
+ stack: details.error.stack
639
+ } : null,
640
+ timestamp: details.timestamp,
641
+ connectionState: details.connectionState,
642
+ channelCreatedAt: details.channelCreatedAt,
643
+ lastOperation: details.lastOperation
644
+ };
645
+
646
+ if (this.monitoring && this.monitoring.error) {
647
+ this.monitoring.error(`MQ Channel Closed: ${details.type}`, logData);
648
+ }
649
+ console.error(`[ServiceWrapper] [MQ] Channel closed: ${details.type} - ${details.reason}`);
650
+ });
651
+
652
+ // Register health shutdown handler
653
+ this.mqClient._transport.on('health:shutdown', (health) => {
654
+ console.error('[ServiceWrapper] [MQ] Health shutdown triggered - shutting down service');
655
+ if (this.monitoring && this.monitoring.error) {
656
+ this.monitoring.error('MQ Health Shutdown', {
657
+ issues: health.issues,
658
+ timestamp: health.timestamp
659
+ });
660
+ }
661
+ // Graceful shutdown
662
+ this.shutdown().then(() => {
663
+ process.exit(1);
664
+ }).catch((err) => {
665
+ console.error('[ServiceWrapper] Shutdown error:', err);
666
+ process.exit(1);
667
+ });
668
+ });
669
+
670
+ this.logger?.info('MQ channel close hooks and health monitoring registered');
671
+ }
587
672
  } catch (error) {
588
673
  const message = `[MQConnector] Unable to connect to RabbitMQ at ${mqUrl}. ` +
589
674
  'Verify that api_services_queuer is running and accessible. ' +