@onlineapps/conn-orch-registry 1.1.21 → 1.1.23

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/conn-orch-registry",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "license": "MIT",
5
5
  "description": "Connector-registry-client provides the core communication mechanism for microservices in this environment. It enables them to interact with a services_registry to receive and fulfill tasks by submitting heartbeats or their API descriptions.",
6
6
  "keywords": [
@@ -39,6 +39,7 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@onlineapps/conn-base-storage": "^1.0.0",
42
+ "@onlineapps/mq-client-core": "^1.0.26",
42
43
  "amqplib": "^0.10.9",
43
44
  "axios": "^1.12.2",
44
45
  "dotenv": "^16.6.1",
@@ -19,6 +19,7 @@
19
19
  */
20
20
 
21
21
  const amqp = require('amqplib');
22
+ const queueConfig = require('@onlineapps/mq-client-core/src/config/queueConfig');
22
23
 
23
24
  /**
24
25
  * Queue manager for the microservice connector.
@@ -59,28 +60,46 @@ class QueueManager {
59
60
  }
60
61
 
61
62
  // Default queues for the registry client
62
- const baseQueues = [
63
- 'workflow'
64
- // Note: ${serviceName}.registry queue is created by RegistryEventConsumer when needed
65
- ];
63
+ const baseQueues = [];
66
64
 
67
65
  const queuesToCreate = baseQueues.concat(additionalQueues);
68
66
 
69
67
  for (const q of queuesToCreate) {
70
- // Use checkQueue first to avoid 406 PRECONDITION-FAILED closing the channel
71
- // If queue doesn't exist (404), then assertQueue to create it
72
- try {
73
- await this.channel.checkQueue(q);
74
- // Queue exists - continue
75
- } catch (checkErr) {
76
- // If queue doesn't exist (404), create it with default options
77
- if (checkErr.code === 404) {
78
- await this.channel.assertQueue(q, { durable: true });
79
- } else {
80
- // Other error (including 406) - queue exists with different args
81
- // Log warning and continue without asserting
82
- console.warn(`[QueueManager] Queue ${q} exists with different arguments, using as-is:`, checkErr.message);
68
+ console.log(`[QueueManager] [REGISTRY] [QUEUE] Ensuring queue: ${q} at ${new Date().toISOString()}`);
69
+
70
+ // CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
71
+ // This prevents 406 PRECONDITION-FAILED errors from TTL mismatches
72
+ let queueOptions = { durable: true };
73
+
74
+ if (queueConfig) {
75
+ try {
76
+ if (queueConfig.isInfrastructureQueue(q)) {
77
+ const infraConfig = queueConfig.getInfrastructureQueueConfig(q);
78
+ queueOptions = {
79
+ durable: infraConfig.durable !== false,
80
+ arguments: { ...infraConfig.arguments }
81
+ };
82
+ console.log(`[QueueManager] [REGISTRY] [QUEUE] Using infrastructure queue config for ${q}:`, JSON.stringify(queueOptions));
83
+ } else {
84
+ console.warn(`[QueueManager] [REGISTRY] [QUEUE] Queue ${q} is not an infrastructure queue, using default options`);
85
+ }
86
+ } catch (configErr) {
87
+ console.warn(`[QueueManager] [REGISTRY] [QUEUE] Failed to get config for ${q}, using defaults:`, configErr.message);
83
88
  }
89
+ } else {
90
+ console.warn(`[QueueManager] [REGISTRY] [QUEUE] queueConfig not available, using default options for ${q}`);
91
+ }
92
+
93
+ // Directly assert queue with canonical configuration (idempotent)
94
+ try {
95
+ const assertStartTime = Date.now();
96
+ await this.channel.assertQueue(q, queueOptions);
97
+ const assertEndTime = Date.now();
98
+ console.log(`[QueueManager] [REGISTRY] [QUEUE] ✓ Queue ${q} asserted (took ${assertEndTime - assertStartTime}ms)`);
99
+ } catch (assertErr) {
100
+ console.error(`[QueueManager] [REGISTRY] [QUEUE] ✗ Failed to assert queue ${q}:`, assertErr.message);
101
+ console.error(`[QueueManager] [REGISTRY] [QUEUE] Error code: ${assertErr.code}`);
102
+ throw assertErr;
84
103
  }
85
104
  }
86
105
  }
@@ -19,6 +19,8 @@ const EventEmitter = require('events');
19
19
  const QueueManager = require('./queueManager');
20
20
  const RegistryEventConsumer = require('./registryEventConsumer');
21
21
  const { v4: uuidv4 } = require('uuid');
22
+ const queueConfig = require('@onlineapps/mq-client-core/src/config/queueConfig');
23
+
22
24
 
23
25
  class ServiceRegistryClient extends EventEmitter {
24
26
  /**
@@ -55,6 +57,7 @@ class ServiceRegistryClient extends EventEmitter {
55
57
 
56
58
  // Validation proof (injected via constructor - DEPENDENCY INJECTION)
57
59
  this.validationProof = validationProof;
60
+ this._verifiedInfraQueues = new Set();
58
61
  }
59
62
 
60
63
  /**
@@ -78,9 +81,16 @@ class ServiceRegistryClient extends EventEmitter {
78
81
  // Create service-specific registry event queue (for certificate delivery)
79
82
  this.serviceRegistryQueue = `${this.serviceName}.registry`;
80
83
 
81
- // Ensure existence of API, registry and service response queues
82
- await this.queueManager.ensureQueues([this.apiQueue, this.registryQueue, this.serviceResponseQueue, this.serviceRegistryQueue]);
84
+ // Ensure existence of service-specific queues only (infrastructure queues must already exist)
85
+ await this.queueManager.ensureQueues([this.serviceResponseQueue, this.serviceRegistryQueue]);
83
86
 
87
+ // CRITICAL: Before consume(), we must assertQueue with correct parameters
88
+ // amqplib's channel.consume() may internally call assertQueue() WITHOUT parameters
89
+ // This causes 406 PRECONDITION-FAILED if queue exists with different arguments
90
+ console.log(`[RegistryClient] [CONSUMER] About to consume from ${this.serviceResponseQueue}`);
91
+ console.log(`[RegistryClient] [CONSUMER] ⚠ WARNING: amqplib's channel.consume() may internally call assertQueue() WITHOUT parameters`);
92
+ console.log(`[RegistryClient] [CONSUMER] ⚠ WARNING: Queue should already be asserted by ensureQueues() above with correct parameters from queueConfig.js`);
93
+
84
94
  // Start consuming service response queue for registry responses
85
95
  await this.queueManager.channel.consume(
86
96
  this.serviceResponseQueue,
@@ -96,6 +106,10 @@ class ServiceRegistryClient extends EventEmitter {
96
106
  );
97
107
 
98
108
  // CRITICAL: Also listen on registry event queue for certificate delivery
109
+ console.log(`[RegistryClient] [CONSUMER] About to consume from ${this.serviceRegistryQueue}`);
110
+ console.log(`[RegistryClient] [CONSUMER] ⚠ WARNING: amqplib's channel.consume() may internally call assertQueue() WITHOUT parameters`);
111
+ console.log(`[RegistryClient] [CONSUMER] ⚠ WARNING: Queue should already be asserted by ensureQueues() above with correct parameters from queueConfig.js`);
112
+
99
113
  await this.queueManager.channel.consume(
100
114
  this.serviceRegistryQueue,
101
115
  msg => {
@@ -190,6 +204,49 @@ class ServiceRegistryClient extends EventEmitter {
190
204
  }
191
205
  }
192
206
 
207
+ /**
208
+ * Ensure an infrastructure queue exists without mutating it.
209
+ * Uses a temporary channel so failures don't kill the primary channel.
210
+ * @param {string} queueName
211
+ * @returns {Promise<void>}
212
+ * @private
213
+ */
214
+ async _ensureInfrastructureQueue(queueName) {
215
+ if (!queueName) {
216
+ return;
217
+ }
218
+
219
+ if (!queueConfig?.isInfrastructureQueue(queueName)) {
220
+ return;
221
+ }
222
+
223
+ if (this._verifiedInfraQueues.has(queueName)) {
224
+ return;
225
+ }
226
+
227
+ if (!this.queueManager?.conn) {
228
+ console.warn(`[RegistryClient] ${this.serviceName}: MQ connection not ready, cannot verify infrastructure queue ${queueName}`);
229
+ return;
230
+ }
231
+
232
+ const verificationChannel = await this.queueManager.conn.createChannel();
233
+ try {
234
+ await verificationChannel.checkQueue(queueName);
235
+ this._verifiedInfraQueues.add(queueName);
236
+ } catch (error) {
237
+ if (error.code === 404) {
238
+ throw new Error(`[RegistryClient] Infrastructure queue '${queueName}' is missing. Ensure the responsible infrastructure service has initialized it.`);
239
+ }
240
+ throw error;
241
+ } finally {
242
+ try {
243
+ await verificationChannel.close();
244
+ } catch (closeErr) {
245
+ console.warn(`[RegistryClient] ${this.serviceName}: Failed to close verification channel for ${queueName}:`, closeErr.message);
246
+ }
247
+ }
248
+ }
249
+
193
250
  /**
194
251
  * Registers the service with the registry.
195
252
  * Registry will validate if the service is properly tested and valid.
@@ -263,15 +320,10 @@ class ServiceRegistryClient extends EventEmitter {
263
320
  }
264
321
 
265
322
  // Send registration message to registry
266
- // Use checkQueue to avoid 406 PRECONDITION-FAILED closing the channel
267
- try {
268
- await this.queueManager.channel.checkQueue(this.registryQueue);
269
- } catch (checkErr) {
270
- if (checkErr.code === 404) {
271
- await this.queueManager.channel.assertQueue(this.registryQueue, { durable: true });
272
- }
273
- // If 406 or other error, queue exists - proceed to publish
274
- }
323
+ // CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
324
+ // This prevents 406 PRECONDITION-FAILED errors from TTL mismatches
325
+ console.log(`[RegistryClient] [PUBLISH] Preparing to publish to ${this.registryQueue}`);
326
+ await this._ensureInfrastructureQueue(this.registryQueue);
275
327
  console.log(`[RegistryClient] ${this.serviceName}: Sending registration message to queue: ${this.registryQueue}`);
276
328
  console.log(`[RegistryClient] ${this.serviceName}: Message type: ${msg.type}, serviceName: ${msg.serviceName}, version: ${msg.version}`);
277
329
  this.queueManager.channel.sendToQueue(
@@ -311,14 +363,9 @@ class ServiceRegistryClient extends EventEmitter {
311
363
  };
312
364
 
313
365
  // Send deregistration message to registry
314
- // Use checkQueue to avoid 406 PRECONDITION-FAILED closing the channel
315
- try {
316
- await this.queueManager.channel.checkQueue(this.registryQueue);
317
- } catch (checkErr) {
318
- if (checkErr.code === 404) {
319
- await this.queueManager.channel.assertQueue(this.registryQueue, { durable: true });
320
- }
321
- }
366
+ // CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
367
+ console.log(`[RegistryClient] [PUBLISH] Preparing to publish to ${this.registryQueue} (deregister)`);
368
+ await this._ensureInfrastructureQueue(this.registryQueue);
322
369
  this.queueManager.channel.sendToQueue(
323
370
  this.registryQueue,
324
371
  Buffer.from(JSON.stringify(msg)),
@@ -361,14 +408,9 @@ class ServiceRegistryClient extends EventEmitter {
361
408
  specificationEndpoint: this.specificationEndpoint,
362
409
  timestamp: new Date().toISOString()
363
410
  };
364
- // Use checkQueue to avoid 406 PRECONDITION-FAILED closing the channel
365
- try {
366
- await this.queueManager.channel.checkQueue(this.registryQueue);
367
- } catch (checkErr) {
368
- if (checkErr.code === 404) {
369
- await this.queueManager.channel.assertQueue(this.registryQueue, { durable: true });
370
- }
371
- }
411
+ // CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
412
+ console.log(`[RegistryClient] [PUBLISH] Preparing to publish to ${this.registryQueue} (heartbeat)`);
413
+ await this._ensureInfrastructureQueue(this.registryQueue);
372
414
  this.queueManager.channel.sendToQueue(
373
415
  this.registryQueue,
374
416
  Buffer.from(JSON.stringify(msg)),
@@ -412,14 +454,9 @@ class ServiceRegistryClient extends EventEmitter {
412
454
  description: apiDescription,
413
455
  timestamp: new Date().toISOString()
414
456
  };
415
- // Use checkQueue to avoid 406 PRECONDITION-FAILED closing the channel
416
- try {
417
- await this.queueManager.channel.checkQueue(this.registryQueue);
418
- } catch (checkErr) {
419
- if (checkErr.code === 404) {
420
- await this.queueManager.channel.assertQueue(this.registryQueue, { durable: true });
421
- }
422
- }
457
+ // CRITICAL: Use queueConfig.js to get correct parameters (TTL, max-length, etc.)
458
+ console.log(`[RegistryClient] [PUBLISH] Preparing to publish to ${this.registryQueue} (apiDescription)`);
459
+ await this._ensureInfrastructureQueue(this.registryQueue);
423
460
  this.queueManager.channel.sendToQueue(
424
461
  this.registryQueue,
425
462
  Buffer.from(JSON.stringify(msg)),