@onlineapps/conn-infra-mq 1.1.40 → 1.1.41

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-infra-mq",
3
- "version": "1.1.40",
3
+ "version": "1.1.41",
4
4
  "description": "A promise-based, broker-agnostic client for sending and receiving messages via RabbitMQ",
5
5
  "main": "src/index.js",
6
6
  "repository": {
@@ -365,121 +365,73 @@ class QueueManager {
365
365
  }
366
366
  }
367
367
 
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)
368
+ // CRITICAL: Use assertQueue() DIRECTLY - it's idempotent and safer than checkQueue() + assertQueue()
369
+ // assertQueue() creates queue if it doesn't exist, or does nothing if it exists with same params
370
+ // If queue exists with different params (406), channel closes but that's OK - we accept the queue
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 checkQueue ${queueName}`;
375
+ channel._lastOperation = `About to assertQueue ${queueName}`;
376
376
  }
377
377
 
378
378
  try {
379
- console.log(`[QueueManager] DEBUG: About to checkQueue ${queueName} (same pattern as ensureQueue)`);
379
+ console.log(`[QueueManager] DEBUG: About to assertQueue ${queueName} directly (idempotent)`);
380
380
  console.log(`[QueueManager] DEBUG: Channel state: exists=${!!channel}, closed=${channel ? (channel.closed === true ? 'true' : channel.closed === false ? 'false' : 'undefined') : 'N/A'}`);
381
381
 
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);
382
+ // CRITICAL: Use assertQueue() DIRECTLY - it's idempotent
383
+ // If queue doesn't exist creates it
384
+ // If queue exists with same params → does nothing (OK)
385
+ // If queue exists with different params → 406, channel closes (but we accept the queue)
386
+ await channel.assertQueue(queueName, queueOptions);
385
387
 
386
- // Queue exists - use it
387
- console.log(`[QueueManager] DEBUG: checkQueue succeeded - queue ${queueName} exists`);
388
+ // Queue created or already exists with same params
389
+ console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}`);
388
390
  if (channel && channel._lastOperation !== undefined) {
389
- channel._lastOperation = `checkQueue ${queueName} succeeded`;
391
+ channel._lastOperation = `assertQueue ${queueName} succeeded`;
390
392
  }
391
393
  queues[queueInfo.type] = queueName;
392
394
  queueCreated = true;
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}`);
395
+ console.info(`[QueueManager] ✓ Created/verified business queue: ${queueName}`);
396
+ } catch (assertErr) {
397
+ console.log(`[QueueManager] DEBUG: assertQueue failed for ${queueName}:`, assertErr.message);
398
+ console.log(`[QueueManager] DEBUG: Error code: ${assertErr.code}`);
397
399
 
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
- // CRITICAL: checkQueue() on 404 may close channel in amqplib, so we must check and recreate if needed
405
- if (checkErr.code === 404) {
406
- console.log(`[QueueManager] DEBUG: Queue ${queueName} doesn't exist (404), creating with assertQueue...`);
407
-
408
- // CRITICAL: checkQueue() on 404 may close channel - check and recreate if needed
409
- if (!channel || channel.closed) {
410
- console.warn(`[QueueManager] DEBUG: Channel closed after checkQueue(404) for ${queueName}, recreating...`);
411
- try {
412
- const newChannel = await transport._connection.createChannel();
413
- newChannel._createdAt = new Date().toISOString();
414
- newChannel._closeReason = null;
415
- newChannel._lastOperation = `Recreated after checkQueue(404) for ${queueName}`;
416
-
417
- newChannel.on('error', (err) => {
418
- console.error('[RabbitMQClient] Recreated queue channel error:', err.message);
419
- newChannel._closeReason = `Error: ${err.message} (code: ${err.code})`;
420
- });
421
- newChannel.on('close', () => {
422
- console.error('[RabbitMQClient] Recreated queue channel closed');
423
- console.error('[RabbitMQClient] Close reason:', newChannel._closeReason || 'Unknown');
424
- });
425
-
426
- channel = newChannel;
427
- transport._queueChannel = channel;
428
- console.log(`[QueueManager] DEBUG: Channel recreated after checkQueue(404) for ${queueName}`);
429
- } catch (recreateErr) {
430
- throw new Error(`Channel closed after checkQueue(404) for ${queueName} and failed to recreate: ${recreateErr.message}`);
431
- }
432
- }
433
-
434
- if (channel && channel._lastOperation !== undefined) {
435
- channel._lastOperation = `About to assertQueue ${queueName} (queue doesn't exist)`;
436
- }
400
+ // If 406 PRECONDITION-FAILED, queue exists with different args - accept it
401
+ // Channel is closed by server, but that's OK - queue exists and we can use it
402
+ if (assertErr.code === 406) {
403
+ console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406), accepting as-is:`, assertErr.message);
404
+ queues[queueInfo.type] = queueName;
405
+ queueCreated = true;
406
+ console.info(`[QueueManager] Business queue exists (different args, accepted): ${queueName}`);
437
407
 
408
+ // Channel is closed, but we need to recreate it for next queue
409
+ // Don't throw error - queue exists, we just need new channel
438
410
  try {
439
- await channel.assertQueue(queueName, queueOptions);
440
- console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}`);
441
- if (channel && channel._lastOperation !== undefined) {
442
- channel._lastOperation = `assertQueue ${queueName} succeeded`;
443
- }
444
- queues[queueInfo.type] = queueName;
445
- queueCreated = true;
446
- console.info(`[QueueManager] ✓ Created business queue: ${queueName}`);
447
- } catch (assertErr) {
448
- // If channel closed during assertQueue, it's a real error
449
- if (!channel || channel.closed) {
450
- throw new Error(`Channel closed during assertQueue for ${queueName} - check channel management`);
451
- }
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}`;
452
415
 
453
- // If 406 PRECONDITION-FAILED, queue exists with different args (race condition?)
454
- if (assertErr.code === 406) {
455
- console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406 from assertQueue):`, assertErr.message);
456
- // Channel should still be open - try checkQueue to verify
457
- if (!channel || channel.closed) {
458
- throw new Error('Channel closed - cannot check existing queue');
459
- }
460
- try {
461
- await channel.checkQueue(queueName);
462
- queues[queueInfo.type] = queueName;
463
- queueCreated = true;
464
- console.info(`[QueueManager] Business queue exists (verified): ${queueName}`);
465
- } catch (verifyErr) {
466
- throw new Error(`Failed to verify existing queue ${queueName}: ${verifyErr.message}`);
467
- }
468
- } else {
469
- // Other errors - rethrow
470
- throw assertErr;
471
- }
416
+ newChannel.on('error', (err) => {
417
+ console.error('[RabbitMQClient] Recreated queue channel error:', err.message);
418
+ newChannel._closeReason = `Error: ${err.message} (code: ${err.code})`;
419
+ });
420
+ newChannel.on('close', () => {
421
+ console.error('[RabbitMQClient] Recreated queue channel closed');
422
+ console.error('[RabbitMQClient] Close reason:', newChannel._closeReason || 'Unknown');
423
+ });
424
+
425
+ channel = newChannel;
426
+ transport._queueChannel = channel;
427
+ console.log(`[QueueManager] DEBUG: Channel recreated after 406 for ${queueName}`);
428
+ } catch (recreateErr) {
429
+ // Even if channel recreation fails, queue exists - log warning but continue
430
+ console.warn(`[QueueManager] Failed to recreate channel after 406 for ${queueName}, but queue exists:`, recreateErr.message);
472
431
  }
473
- } else if (checkErr.code === 406) {
474
- // Queue exists with different args (406 from checkQueue) - use it as-is
475
- // CRITICAL: checkQueue() on 406 does NOT close channel (unlike assertQueue() on 406)
476
- console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406 from checkQueue), using as-is:`, checkErr.message);
477
- queues[queueInfo.type] = queueName;
478
- queueCreated = true;
479
- console.info(`[QueueManager] ✓ Business queue exists (different args): ${queueName}`);
480
432
  } else {
481
- // Other error - rethrow
482
- throw checkErr;
433
+ // Other error - critical, cannot continue
434
+ throw new Error(`Failed to create business queue ${queueName}: ${assertErr.message}`);
483
435
  }
484
436
  }
485
437