@onlineapps/conn-infra-mq 1.1.44 → 1.1.46
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/layers/QueueManager.js +14 -113
package/package.json
CHANGED
|
@@ -36,6 +36,14 @@ class QueueManager {
|
|
|
36
36
|
if (!transport || !transport.channel) {
|
|
37
37
|
throw new Error('MQ client not connected');
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
// CRITICAL: Business queues MUST be created via setupServiceQueues() AFTER registration
|
|
41
|
+
// Business queues should NOT be created via ensureQueue() before registration
|
|
42
|
+
// This prevents queues from being created with wrong arguments or before service is registered
|
|
43
|
+
if (queueConfig.isBusinessQueue(queueName)) {
|
|
44
|
+
throw new Error(`Business queue ${queueName} must be created via setupServiceQueues() after successful registration. Do not use ensureQueue() for business queues.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
39
47
|
// Use queueChannel for queue operations to avoid RPC reply queue issues
|
|
40
48
|
// queueChannel is a regular channel, not ConfirmChannel
|
|
41
49
|
const channel = transport.queueChannel || transport.channel;
|
|
@@ -55,25 +63,6 @@ class QueueManager {
|
|
|
55
63
|
console.warn(`[QueueManager] Infrastructure queue config not found for ${queueName}, using provided options:`, error.message);
|
|
56
64
|
queueOptions = this._buildQueueOptions(queueName, options);
|
|
57
65
|
}
|
|
58
|
-
} else if (queueConfig.isBusinessQueue(queueName)) {
|
|
59
|
-
// Business queue - use central business queue config
|
|
60
|
-
try {
|
|
61
|
-
const parsed = queueConfig.parseBusinessQueue(queueName);
|
|
62
|
-
if (parsed) {
|
|
63
|
-
const businessConfig = queueConfig.getBusinessQueueConfig(parsed.queueType, parsed.serviceName);
|
|
64
|
-
queueOptions = {
|
|
65
|
-
durable: businessConfig.durable !== false,
|
|
66
|
-
arguments: { ...businessConfig.arguments }
|
|
67
|
-
};
|
|
68
|
-
} else {
|
|
69
|
-
// Fallback to provided options
|
|
70
|
-
queueOptions = this._buildQueueOptions(queueName, options);
|
|
71
|
-
}
|
|
72
|
-
} catch (error) {
|
|
73
|
-
// If config not found, fall back to provided options
|
|
74
|
-
console.warn(`[QueueManager] Business queue config not found for ${queueName}, using provided options:`, error.message);
|
|
75
|
-
queueOptions = this._buildQueueOptions(queueName, options);
|
|
76
|
-
}
|
|
77
66
|
} else {
|
|
78
67
|
// Unknown queue type - use provided options
|
|
79
68
|
queueOptions = this._buildQueueOptions(queueName, options);
|
|
@@ -365,96 +354,8 @@ class QueueManager {
|
|
|
365
354
|
}
|
|
366
355
|
}
|
|
367
356
|
|
|
368
|
-
// CRITICAL: Check if queue exists with different arguments BEFORE assertQueue
|
|
369
|
-
// If queue exists with wrong args, delete it and create with correct args
|
|
370
|
-
// This prevents 406 errors and channel closure
|
|
371
|
-
let queueNeedsRecreation = false;
|
|
372
|
-
let existingQueueInfo = null;
|
|
373
|
-
|
|
374
|
-
try {
|
|
375
|
-
// Use checkQueue to get existing queue info (this may close channel on 404, but that's OK)
|
|
376
|
-
// We use a separate channel for this check to avoid closing the main channel
|
|
377
|
-
let checkChannel = channel;
|
|
378
|
-
try {
|
|
379
|
-
existingQueueInfo = await checkChannel.checkQueue(queueName);
|
|
380
|
-
console.log(`[QueueManager] DEBUG: Queue ${queueName} exists, checking arguments...`);
|
|
381
|
-
|
|
382
|
-
// Compare existing queue arguments with expected arguments
|
|
383
|
-
const existingArgs = existingQueueInfo.arguments || {};
|
|
384
|
-
const expectedArgs = queueOptions.arguments || {};
|
|
385
|
-
|
|
386
|
-
// Check if arguments match (deep comparison of key values)
|
|
387
|
-
const argsMatch = Object.keys(expectedArgs).every(key => {
|
|
388
|
-
const existing = existingArgs[key];
|
|
389
|
-
const expected = expectedArgs[key];
|
|
390
|
-
|
|
391
|
-
// Handle special case: x-dead-letter-routing-key may have placeholder replaced
|
|
392
|
-
if (key === 'x-dead-letter-routing-key') {
|
|
393
|
-
const expectedRoutingKey = expected.replace('{service}', serviceName);
|
|
394
|
-
return existing === expectedRoutingKey || existing === expected;
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
return existing === expected;
|
|
398
|
-
}) && Object.keys(existingArgs).length === Object.keys(expectedArgs).length;
|
|
399
|
-
|
|
400
|
-
if (!argsMatch) {
|
|
401
|
-
console.warn(`[QueueManager] Queue ${queueName} exists with different arguments, will delete and recreate`);
|
|
402
|
-
console.warn(`[QueueManager] Existing args:`, JSON.stringify(existingArgs));
|
|
403
|
-
console.warn(`[QueueManager] Expected args:`, JSON.stringify(expectedArgs));
|
|
404
|
-
queueNeedsRecreation = true;
|
|
405
|
-
} else {
|
|
406
|
-
console.log(`[QueueManager] DEBUG: Queue ${queueName} exists with correct arguments`);
|
|
407
|
-
}
|
|
408
|
-
} catch (checkErr) {
|
|
409
|
-
if (checkErr.code === 404) {
|
|
410
|
-
// Queue doesn't exist - will be created
|
|
411
|
-
console.log(`[QueueManager] DEBUG: Queue ${queueName} does not exist, will create`);
|
|
412
|
-
existingQueueInfo = null;
|
|
413
|
-
} else {
|
|
414
|
-
// Other error - log but continue (will try assertQueue anyway)
|
|
415
|
-
console.warn(`[QueueManager] checkQueue failed for ${queueName}:`, checkErr.message);
|
|
416
|
-
// Channel may be closed, but we'll recreate it before assertQueue
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
} catch (checkError) {
|
|
420
|
-
// If checkQueue fails (e.g., channel closed), continue anyway
|
|
421
|
-
// assertQueue will handle it
|
|
422
|
-
console.warn(`[QueueManager] Failed to check queue ${queueName}, will try assertQueue:`, checkError.message);
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// If queue exists with wrong args, delete it first
|
|
426
|
-
if (queueNeedsRecreation && existingQueueInfo) {
|
|
427
|
-
console.log(`[QueueManager] Deleting queue ${queueName} to recreate with correct arguments...`);
|
|
428
|
-
try {
|
|
429
|
-
// Recreate channel if needed (checkQueue may have closed it)
|
|
430
|
-
if (!channel || channel.closed) {
|
|
431
|
-
channel = await transport._connection.createChannel();
|
|
432
|
-
channel._createdAt = new Date().toISOString();
|
|
433
|
-
channel._closeReason = null;
|
|
434
|
-
channel._lastOperation = `Recreated before deleteQueue ${queueName}`;
|
|
435
|
-
|
|
436
|
-
channel.on('error', (err) => {
|
|
437
|
-
console.error('[RabbitMQClient] Recreated queue channel error:', err.message);
|
|
438
|
-
channel._closeReason = `Error: ${err.message} (code: ${err.code})`;
|
|
439
|
-
});
|
|
440
|
-
channel.on('close', () => {
|
|
441
|
-
console.error('[RabbitMQClient] Recreated queue channel closed');
|
|
442
|
-
console.error('[RabbitMQClient] Close reason:', channel._closeReason || 'Unknown');
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
transport._queueChannel = channel;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
await channel.deleteQueue(queueName);
|
|
449
|
-
console.log(`[QueueManager] ✓ Deleted queue ${queueName} for recreation`);
|
|
450
|
-
} catch (deleteErr) {
|
|
451
|
-
// If delete fails, log warning but continue - assertQueue will handle it
|
|
452
|
-
console.warn(`[QueueManager] Failed to delete queue ${queueName}, will try assertQueue anyway:`, deleteErr.message);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
357
|
// CRITICAL: Ensure channel is usable before assertQueue
|
|
457
|
-
// Recreate if closed (may have been closed by
|
|
358
|
+
// Recreate if closed (may have been closed by previous operations)
|
|
458
359
|
if (!channel || channel.closed) {
|
|
459
360
|
console.log(`[QueueManager] DEBUG: Channel is closed before assertQueue ${queueName}, recreating...`);
|
|
460
361
|
channel = await transport._connection.createChannel();
|
|
@@ -505,13 +406,13 @@ class QueueManager {
|
|
|
505
406
|
console.log(`[QueueManager] DEBUG: assertQueue failed for ${queueName}:`, assertErr.message);
|
|
506
407
|
console.log(`[QueueManager] DEBUG: Error code: ${assertErr.code}`);
|
|
507
408
|
|
|
508
|
-
// If 406 PRECONDITION-FAILED,
|
|
509
|
-
//
|
|
409
|
+
// If 406 PRECONDITION-FAILED, queue exists with different args
|
|
410
|
+
// Delete it and recreate with correct args
|
|
510
411
|
if (assertErr.code === 406) {
|
|
511
|
-
console.
|
|
512
|
-
console.
|
|
412
|
+
console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406), deleting and recreating...`);
|
|
413
|
+
console.warn(`[QueueManager] Expected args:`, JSON.stringify(queueOptions.arguments));
|
|
513
414
|
|
|
514
|
-
//
|
|
415
|
+
// Delete queue and recreate with correct args
|
|
515
416
|
try {
|
|
516
417
|
// Recreate channel (closed by 406)
|
|
517
418
|
channel = await transport._connection.createChannel();
|