@onlineapps/conn-infra-mq 1.1.37 → 1.1.39
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 +69 -85
package/package.json
CHANGED
|
@@ -266,7 +266,7 @@ class QueueManager {
|
|
|
266
266
|
console.error('[RabbitMQClient] Close reason:', channel._closeReason || 'Unknown');
|
|
267
267
|
});
|
|
268
268
|
|
|
269
|
-
transport.
|
|
269
|
+
transport._queueChannel = channel;
|
|
270
270
|
console.log(`[QueueManager] DEBUG: Channel recreated (was null) before ${queueInfo.name}`);
|
|
271
271
|
} else {
|
|
272
272
|
// Check if channel is closed - amqplib may not set closed property immediately
|
|
@@ -305,7 +305,7 @@ class QueueManager {
|
|
|
305
305
|
});
|
|
306
306
|
|
|
307
307
|
channel = newChannel;
|
|
308
|
-
transport.
|
|
308
|
+
transport._queueChannel = channel;
|
|
309
309
|
console.log(`[QueueManager] DEBUG: Channel recreated (check failed) before ${queueInfo.name}`);
|
|
310
310
|
channelUsable = true;
|
|
311
311
|
} catch (recreateErr) {
|
|
@@ -365,110 +365,94 @@ class QueueManager {
|
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
// CRITICAL: Use
|
|
369
|
-
//
|
|
370
|
-
//
|
|
368
|
+
// CRITICAL: Use the SAME pattern as ensureQueue() - checkQueue() FIRST, then assertQueue() only if 404
|
|
369
|
+
// This prevents channel closure on 406 PRECONDITION-FAILED
|
|
370
|
+
// Pattern: checkQueue() -> if 404, assertQueue() -> if 406, use existing queue (channel stays open)
|
|
371
371
|
let queueCreated = false;
|
|
372
372
|
|
|
373
|
-
//
|
|
373
|
+
// Track operation on channel for debugging
|
|
374
374
|
if (channel && channel._lastOperation !== undefined) {
|
|
375
|
-
channel._lastOperation = `About to
|
|
375
|
+
channel._lastOperation = `About to checkQueue ${queueName}`;
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
try {
|
|
379
|
-
console.log(`[QueueManager] DEBUG: About to
|
|
379
|
+
console.log(`[QueueManager] DEBUG: About to checkQueue ${queueName} (same pattern as ensureQueue)`);
|
|
380
380
|
console.log(`[QueueManager] DEBUG: Channel state: exists=${!!channel}, closed=${channel ? (channel.closed === true ? 'true' : channel.closed === false ? 'false' : 'undefined') : 'N/A'}`);
|
|
381
|
-
console.log(`[QueueManager] DEBUG: Channel created at: ${channel?._createdAt || 'N/A'}`);
|
|
382
|
-
console.log(`[QueueManager] DEBUG: Queue options:`, JSON.stringify(queueOptions, null, 2));
|
|
383
381
|
|
|
384
|
-
|
|
382
|
+
// CRITICAL: Use checkQueue() FIRST (same as ensureQueue() pattern)
|
|
383
|
+
// This prevents channel closure on 406 - if queue exists with different args, checkQueue() returns 406 but channel stays open
|
|
384
|
+
await channel.checkQueue(queueName);
|
|
385
385
|
|
|
386
|
-
|
|
386
|
+
// Queue exists - use it
|
|
387
|
+
console.log(`[QueueManager] DEBUG: checkQueue succeeded - queue ${queueName} exists`);
|
|
387
388
|
if (channel && channel._lastOperation !== undefined) {
|
|
388
|
-
channel._lastOperation = `
|
|
389
|
+
channel._lastOperation = `checkQueue ${queueName} succeeded`;
|
|
389
390
|
}
|
|
390
391
|
queues[queueInfo.type] = queueName;
|
|
391
392
|
queueCreated = true;
|
|
392
|
-
console.info(`[QueueManager] ✓
|
|
393
|
-
} catch (
|
|
394
|
-
console.
|
|
395
|
-
console.
|
|
396
|
-
console.error(`[QueueManager] DEBUG: Channel state after error: exists=${!!channel}, closed=${channel ? (channel.closed === true ? 'true' : channel.closed === false ? 'false' : 'undefined') : 'N/A'}`);
|
|
397
|
-
console.error(`[QueueManager] DEBUG: Channel close reason: ${channel?._closeReason || 'N/A'}`);
|
|
393
|
+
console.info(`[QueueManager] ✓ Business queue exists: ${queueName}`);
|
|
394
|
+
} catch (checkErr) {
|
|
395
|
+
console.log(`[QueueManager] DEBUG: checkQueue failed for ${queueName}:`, checkErr.message);
|
|
396
|
+
console.log(`[QueueManager] DEBUG: Error code: ${checkErr.code}`);
|
|
398
397
|
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
398
|
+
// Check if channel is still open
|
|
399
|
+
if (!channel || channel.closed) {
|
|
400
|
+
throw new Error('Channel closed during checkQueue - cannot verify queue');
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// If queue doesn't exist (404), create it using assertQueue
|
|
404
|
+
if (checkErr.code === 404) {
|
|
405
|
+
console.log(`[QueueManager] DEBUG: Queue ${queueName} doesn't exist (404), creating with assertQueue...`);
|
|
403
406
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
try {
|
|
407
|
-
// Wait a tiny bit for channel close event to propagate
|
|
408
|
-
await new Promise(resolve => setImmediate(resolve));
|
|
409
|
-
|
|
410
|
-
// Create new channel
|
|
411
|
-
const newChannel = await transport._connection.createChannel();
|
|
412
|
-
newChannel._createdAt = new Date().toISOString();
|
|
413
|
-
newChannel._closeReason = null;
|
|
414
|
-
newChannel._lastOperation = `Recreated after 406 for ${queueName}`;
|
|
415
|
-
|
|
416
|
-
// Set up error/close handlers for new channel
|
|
417
|
-
newChannel.on('error', (err) => {
|
|
418
|
-
console.error('[RabbitMQClient] New queue channel error:', err.message);
|
|
419
|
-
newChannel._closeReason = `Error: ${err.message} (code: ${err.code})`;
|
|
420
|
-
});
|
|
421
|
-
newChannel.on('close', () => {
|
|
422
|
-
console.error('[RabbitMQClient] New queue channel closed');
|
|
423
|
-
console.error('[RabbitMQClient] Close reason:', newChannel._closeReason || 'Unknown');
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
// Update references
|
|
427
|
-
channel = newChannel;
|
|
428
|
-
transport.queueChannel = channel;
|
|
429
|
-
|
|
430
|
-
console.log(`[QueueManager] DEBUG: Channel recreated after 406 for ${queueName}`);
|
|
431
|
-
console.log(`[QueueManager] DEBUG: New channel created at: ${channel._createdAt}`);
|
|
432
|
-
} catch (recreateErr) {
|
|
433
|
-
console.error(`[QueueManager] DEBUG: Failed to recreate channel after 406:`, recreateErr.message);
|
|
434
|
-
throw new Error(`Failed to recreate channel after 406 for ${queueName}: ${recreateErr.message}`);
|
|
407
|
+
if (channel && channel._lastOperation !== undefined) {
|
|
408
|
+
channel._lastOperation = `About to assertQueue ${queueName} (queue doesn't exist)`;
|
|
435
409
|
}
|
|
436
410
|
|
|
437
|
-
// Queue exists (just with different args) - accept it
|
|
438
|
-
queues[queueInfo.type] = queueName;
|
|
439
|
-
queueCreated = true;
|
|
440
|
-
} else if (assertErr.message && assertErr.message.includes('Channel closed')) {
|
|
441
|
-
// Channel closed error (not 406) - recreate channel
|
|
442
|
-
console.error(`[QueueManager] DEBUG: Channel was closed during assertQueue for ${queueName} (not 406), recreating...`);
|
|
443
411
|
try {
|
|
444
|
-
await
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
console.error('[RabbitMQClient] Close reason:', newChannel._closeReason || 'Unknown');
|
|
458
|
-
});
|
|
459
|
-
|
|
460
|
-
channel = newChannel;
|
|
461
|
-
transport.queueChannel = channel;
|
|
412
|
+
await channel.assertQueue(queueName, queueOptions);
|
|
413
|
+
console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}`);
|
|
414
|
+
if (channel && channel._lastOperation !== undefined) {
|
|
415
|
+
channel._lastOperation = `assertQueue ${queueName} succeeded`;
|
|
416
|
+
}
|
|
417
|
+
queues[queueInfo.type] = queueName;
|
|
418
|
+
queueCreated = true;
|
|
419
|
+
console.info(`[QueueManager] ✓ Created business queue: ${queueName}`);
|
|
420
|
+
} catch (assertErr) {
|
|
421
|
+
// If channel closed during assertQueue, it's a real error
|
|
422
|
+
if (!channel || channel.closed) {
|
|
423
|
+
throw new Error(`Channel closed during assertQueue for ${queueName} - check channel management`);
|
|
424
|
+
}
|
|
462
425
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
426
|
+
// If 406 PRECONDITION-FAILED, queue exists with different args (race condition?)
|
|
427
|
+
if (assertErr.code === 406) {
|
|
428
|
+
console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406 from assertQueue):`, assertErr.message);
|
|
429
|
+
// Channel should still be open - try checkQueue to verify
|
|
430
|
+
if (!channel || channel.closed) {
|
|
431
|
+
throw new Error('Channel closed - cannot check existing queue');
|
|
432
|
+
}
|
|
433
|
+
try {
|
|
434
|
+
await channel.checkQueue(queueName);
|
|
435
|
+
queues[queueInfo.type] = queueName;
|
|
436
|
+
queueCreated = true;
|
|
437
|
+
console.info(`[QueueManager] ✓ Business queue exists (verified): ${queueName}`);
|
|
438
|
+
} catch (verifyErr) {
|
|
439
|
+
throw new Error(`Failed to verify existing queue ${queueName}: ${verifyErr.message}`);
|
|
440
|
+
}
|
|
441
|
+
} else {
|
|
442
|
+
// Other errors - rethrow
|
|
443
|
+
throw assertErr;
|
|
444
|
+
}
|
|
466
445
|
}
|
|
467
|
-
|
|
468
|
-
|
|
446
|
+
} else if (checkErr.code === 406) {
|
|
447
|
+
// Queue exists with different args (406 from checkQueue) - use it as-is
|
|
448
|
+
// CRITICAL: checkQueue() on 406 does NOT close channel (unlike assertQueue() on 406)
|
|
449
|
+
console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406 from checkQueue), using as-is:`, checkErr.message);
|
|
450
|
+
queues[queueInfo.type] = queueName;
|
|
451
|
+
queueCreated = true;
|
|
452
|
+
console.info(`[QueueManager] ✓ Business queue exists (different args): ${queueName}`);
|
|
469
453
|
} else {
|
|
470
|
-
// Other error -
|
|
471
|
-
throw
|
|
454
|
+
// Other error - rethrow
|
|
455
|
+
throw checkErr;
|
|
472
456
|
}
|
|
473
457
|
}
|
|
474
458
|
|