@onlineapps/service-wrapper 2.1.85 → 2.1.86

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.
@@ -12,14 +12,8 @@
12
12
  "heartbeatInterval": 30000
13
13
  },
14
14
  "infrastructureGate": {
15
- "maxWaitMs": 300000,
16
- "checkIntervalMs": 5000
17
- },
18
- "infrastructureVerify": {
19
- "maxRetries": 12,
20
- "baseDelayMs": 5000,
21
- "maxDelayMs": 30000,
22
- "queueCheckTimeoutMs": 5000
15
+ "maxWaitMs": 5000,
16
+ "checkIntervalMs": 2000
23
17
  },
24
18
  "monitoring": {
25
19
  "enabled": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlineapps/service-wrapper",
3
- "version": "2.1.85",
3
+ "version": "2.1.86",
4
4
  "description": "Thin orchestration layer for microservices - delegates all infrastructure concerns to specialized connectors",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -935,143 +935,34 @@ class ServiceWrapper {
935
935
  * 1. Service has certificate (validated + registered) - checked in _startWorkflowListenersIfReady()
936
936
  * 2. Infrastructure is ready - checked in this method
937
937
  *
938
- * Checks:
939
- * 1. All infrastructure services are UP (via Redis key infrastructure:health:all)
940
- * 2. Required infrastructure queues exist (workflow.init, registry.register, etc.)
938
+ * SEPARATION OF CONCERNS:
939
+ * - Business services MUST NOT check infrastructure queues directly.
940
+ * - Business services MUST trust Registry's infrastructure:health:all flag.
941
+ * - Infrastructure services are responsible for their own queue health.
942
+ * - If infrastructure is not ready within timeout, business service exits (Docker restarts it).
941
943
  *
942
- * Uses exponential backoff retry mechanism if infrastructure not ready.
943
944
  * @private
944
945
  */
945
946
  async _verifyInfrastructureReady(serviceName) {
946
- const maxRetries = this.config.wrapper?.infrastructureVerify?.maxRetries;
947
- const baseDelay = this.config.wrapper?.infrastructureVerify?.baseDelayMs;
948
- const maxDelay = this.config.wrapper?.infrastructureVerify?.maxDelayMs;
949
- const queueCheckTimeoutMs = this.config.wrapper?.infrastructureVerify?.queueCheckTimeoutMs;
950
-
951
- if (typeof maxRetries !== 'number' || Number.isNaN(maxRetries) || maxRetries <= 0) {
952
- throw new Error(`[InfrastructureVerify] Invalid configuration - wrapper.infrastructureVerify.maxRetries must be a positive number, got: ${maxRetries}`);
953
- }
954
- if (typeof baseDelay !== 'number' || Number.isNaN(baseDelay) || baseDelay <= 0) {
955
- throw new Error(`[InfrastructureVerify] Invalid configuration - wrapper.infrastructureVerify.baseDelayMs must be a positive number, got: ${baseDelay}`);
956
- }
957
- if (typeof maxDelay !== 'number' || Number.isNaN(maxDelay) || maxDelay <= 0) {
958
- throw new Error(`[InfrastructureVerify] Invalid configuration - wrapper.infrastructureVerify.maxDelayMs must be a positive number, got: ${maxDelay}`);
959
- }
960
- if (typeof queueCheckTimeoutMs !== 'number' || Number.isNaN(queueCheckTimeoutMs) || queueCheckTimeoutMs <= 0) {
961
- throw new Error(`[InfrastructureVerify] Invalid configuration - wrapper.infrastructureVerify.queueCheckTimeoutMs must be a positive number, got: ${queueCheckTimeoutMs}`);
962
- }
963
-
964
- // Required infrastructure queues that must exist before business queues can be created
965
- const requiredInfrastructureQueues = [
966
- 'workflow.init', // Gateway responsibility (workflow entrypoint)
967
- 'workflow.control', // Gateway responsibility (shared control-flow steps)
968
- 'registry.register', // Registry responsibility
969
- ];
947
+ this.logger?.info('[InfrastructureReady] Checking infrastructure status via Registry (trusting infrastructure:health:all flag)...');
970
948
 
971
- // Optional infrastructure queues (may not exist if services are not running)
972
- const optionalInfrastructureQueues = [
973
- 'validation.requests', // Validator responsibility
974
- 'workflow.completed', // Delivery Dispatcher responsibility
975
- 'workflow.failed' // Delivery Dispatcher responsibility
976
- ];
977
-
978
- this.logger?.info('[InfrastructureVerify] Starting infrastructure readiness verification...', {
979
- maxRetries,
980
- baseDelay,
981
- requiredQueues: requiredInfrastructureQueues
982
- });
983
-
984
- for (let attempt = 1; attempt <= maxRetries; attempt++) {
985
- try {
986
- await this._waitForInfrastructureGate('business queue setup');
987
-
988
- // Step 2: Verify required infrastructure queues exist
989
- this.logger?.info('[InfrastructureVerify] Verifying required infrastructure queues exist...');
990
-
991
- const transport = this.mqClient._transport;
992
- if (!transport || !transport._queueChannel) {
993
- throw new Error('MQ transport not initialized - cannot verify infrastructure queues');
994
- }
995
-
996
- const channel = transport._queueChannel;
997
- if (channel.closed) {
998
- throw new Error('MQ channel is closed - cannot verify infrastructure queues');
999
- }
1000
-
1001
- const missingQueues = [];
1002
- for (const queueName of requiredInfrastructureQueues) {
1003
- try {
1004
- // Add timeout to prevent hanging on checkQueue
1005
- const checkPromise = channel.checkQueue(queueName);
1006
- const checkTimeoutPromise = new Promise((_, reject) => {
1007
- setTimeout(() => {
1008
- reject(new Error(`checkQueue timeout after ${queueCheckTimeoutMs}ms`));
1009
- }, queueCheckTimeoutMs);
1010
- });
1011
-
1012
- await Promise.race([checkPromise, checkTimeoutPromise]);
1013
- this.logger?.info(`[InfrastructureVerify] ✓ Queue exists: ${queueName}`);
1014
- } catch (checkErr) {
1015
- if (checkErr.code === 404 || checkErr.message.includes('timeout')) {
1016
- missingQueues.push(queueName);
1017
- this.logger?.warn(`[InfrastructureVerify] ✗ Queue missing or timeout: ${queueName} (${checkErr.message})`);
1018
- } else {
1019
- // Other error (e.g., channel closed) - treat as missing
1020
- missingQueues.push(queueName);
1021
- this.logger?.warn(`[InfrastructureVerify] ✗ Cannot check queue ${queueName}: ${checkErr.message}`);
1022
- }
1023
- }
1024
- }
1025
-
1026
- if (missingQueues.length > 0) {
1027
- const queueDetails = missingQueues.map((queueName) => {
1028
- const owner = INFRA_QUEUE_OWNERS[queueName] || 'responsible infrastructure service';
1029
- return `${queueName} (owner: ${owner})`;
1030
- });
1031
- throw new Error(
1032
- `[InfrastructureVerify] Required RabbitMQ queue(s) missing: ${queueDetails.join(', ')}. ` +
1033
- 'Infrastructure service(s) responsible for these queues are not ready yet. ' +
1034
- 'Resolve the infrastructure issue and restart the business service.'
1035
- );
1036
- }
1037
-
1038
- // Step 3: Log optional queues status (for debugging)
1039
- for (const queueName of optionalInfrastructureQueues) {
1040
- try {
1041
- const checkPromise = channel.checkQueue(queueName);
1042
- const checkTimeoutPromise = new Promise((_, reject) => {
1043
- setTimeout(() => reject(new Error('timeout')), queueCheckTimeoutMs);
1044
- });
1045
- await Promise.race([checkPromise, checkTimeoutPromise]);
1046
- this.logger?.info(`[InfrastructureVerify] ✓ Optional queue exists: ${queueName}`);
1047
- } catch (checkErr) {
1048
- if (checkErr.code === 404 || checkErr.message.includes('timeout')) {
1049
- this.logger?.debug(`[InfrastructureVerify] Optional queue missing or timeout (not critical): ${queueName}`);
1050
- }
1051
- }
1052
- }
1053
-
1054
- // All checks passed!
1055
- this.logger?.info('[InfrastructureVerify] ✓ Infrastructure verification complete - all required queues exist');
1056
- return;
1057
-
1058
- } catch (error) {
1059
- if (attempt === maxRetries) {
1060
- // Final attempt failed - throw error
1061
- this.logger?.error('[InfrastructureVerify] ✗ Infrastructure verification failed after all retries', {
1062
- error: error.message,
1063
- stack: error.stack
1064
- });
1065
- throw new Error(`Infrastructure verification failed for ${serviceName}: ${error.message}`);
1066
- }
1067
-
1068
- // Not final attempt - continue retry loop
1069
- const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
1070
- this.logger?.warn(`[InfrastructureVerify] Verification failed (attempt ${attempt}/${maxRetries}), retrying in ${delay}ms...`, {
1071
- error: error.message
1072
- });
1073
- await new Promise(resolve => setTimeout(resolve, delay));
1074
- }
949
+ try {
950
+ // Single check - if infra not ready, fail fast and let Docker restart
951
+ await this._waitForInfrastructureGate('business queue setup');
952
+ this.logger?.info('[InfrastructureReady] Infrastructure is ready (infrastructure:health:all = true)');
953
+ } catch (error) {
954
+ // Infrastructure not ready - fail fast with clear message
955
+ this.logger?.error('[InfrastructureReady] ✗ Infrastructure not ready - service will exit', {
956
+ error: error.message,
957
+ serviceName,
958
+ action: 'Docker will restart the service. Check infrastructure services (Gateway, Registry, Validator, Delivery, Monitoring).'
959
+ });
960
+ throw new Error(
961
+ `[InfrastructureReady] Infrastructure not ready for ${serviceName}. ` +
962
+ 'Registry reports infrastructure:health:all != true. ' +
963
+ 'Check infrastructure services and their logs. ' +
964
+ 'This service will exit and Docker will restart it.'
965
+ );
1075
966
  }
1076
967
  }
1077
968