@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 +2 -1
- package/src/queueManager.js +36 -17
- package/src/registryClient.js +72 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onlineapps/conn-orch-registry",
|
|
3
|
-
"version": "1.1.
|
|
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",
|
package/src/queueManager.js
CHANGED
|
@@ -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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
}
|
package/src/registryClient.js
CHANGED
|
@@ -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
|
|
82
|
-
await this.queueManager.ensureQueues([this.
|
|
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
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
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
|
|
315
|
-
|
|
316
|
-
|
|
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
|
|
365
|
-
|
|
366
|
-
|
|
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
|
|
416
|
-
|
|
417
|
-
|
|
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)),
|