@onlineapps/conn-infra-mq 1.1.30 → 1.1.32

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.30",
3
+ "version": "1.1.32",
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": {
@@ -294,45 +294,69 @@ class QueueManager {
294
294
  }
295
295
 
296
296
  // CRITICAL: Use assertQueue directly - if queue exists with different args (406), that's OK
297
- // We'll handle it gracefully, but channel should NOT close
297
+ // BUT: 406 PRECONDITION-FAILED closes the channel in amqplib!
298
+ // Solution: Catch 406, recreate channel immediately, and continue
299
+ let queueCreated = false;
298
300
  try {
299
- // Check if channel is still open before each operation
300
- if (!channel || channel.closed) {
301
- console.error(`[QueueManager] DEBUG: Channel closed before creating ${queueName}`);
302
- throw new Error(`Channel closed before creating ${queueName} - cannot continue`);
303
- }
304
-
305
301
  console.log(`[QueueManager] DEBUG: About to assertQueue ${queueName} with options:`, JSON.stringify(queueOptions, null, 2));
306
- console.log(`[QueueManager] DEBUG: Channel state before assertQueue: closed=${channel.closed}`);
307
302
 
308
303
  await channel.assertQueue(queueName, queueOptions);
309
304
 
310
- console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}, channel closed=${channel.closed}`);
305
+ console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}`);
311
306
  queues[queueInfo.type] = queueName;
307
+ queueCreated = true;
312
308
  console.info(`[QueueManager] ✓ Created business queue: ${queueName}`);
313
309
  } catch (assertErr) {
314
310
  console.error(`[QueueManager] DEBUG: assertQueue failed for ${queueName}:`, assertErr.message);
315
- console.error(`[QueueManager] DEBUG: Error code: ${assertErr.code}, channel closed: ${channel ? channel.closed : 'N/A'}`);
316
- console.error(`[QueueManager] DEBUG: Stack trace:`, assertErr.stack);
311
+ console.error(`[QueueManager] DEBUG: Error code: ${assertErr.code}`);
317
312
 
318
- // If channel closed, this is a critical error
319
- if (!channel || channel.closed) {
320
- console.error(`[QueueManager] DEBUG: Channel was closed during assertQueue for ${queueName}`);
321
- throw new Error(`Channel closed during assertQueue for ${queueName} - cannot create remaining queues`);
322
- }
323
-
324
- // If 406 PRECONDITION-FAILED, queue exists with different args - use it as-is
325
- // CRITICAL: Do NOT use checkQueue() here - it closes channel on 404!
326
- // If assertQueue() returned 406, queue exists (just with different args) - that's OK
313
+ // If 406 PRECONDITION-FAILED, queue exists with different args - channel is closed, recreate it IMMEDIATELY
314
+ // CRITICAL: amqplib closes channel on 406, so we MUST recreate it to continue
327
315
  if (assertErr.code === 406) {
328
- console.warn(`[QueueManager] Queue ${queueName} exists with different arguments, using as-is:`, assertErr.message);
316
+ console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406), channel will be closed. Recreating channel...`);
317
+
318
+ // Recreate channel IMMEDIATELY - 406 closes it synchronously
319
+ try {
320
+ // Wait a tiny bit for channel close event to propagate
321
+ await new Promise(resolve => setImmediate(resolve));
322
+ channel = await transport._connection.createChannel();
323
+ transport.queueChannel = channel;
324
+ console.log(`[QueueManager] DEBUG: Channel recreated after 406 for ${queueName}`);
325
+ } catch (recreateErr) {
326
+ throw new Error(`Failed to recreate channel after 406 for ${queueName}: ${recreateErr.message}`);
327
+ }
328
+
329
329
  // Queue exists (just with different args) - accept it
330
330
  queues[queueInfo.type] = queueName;
331
+ queueCreated = true;
331
332
  } else {
332
- // Other error - critical, cannot continue
333
- throw new Error(`Failed to create business queue ${queueName}: ${assertErr.message}`);
333
+ // Other error - check if it's a channel closed error
334
+ if (assertErr.message && assertErr.message.includes('Channel closed')) {
335
+ console.error(`[QueueManager] DEBUG: Channel was closed during assertQueue for ${queueName}, recreating...`);
336
+ // Try to recreate channel
337
+ try {
338
+ await new Promise(resolve => setImmediate(resolve));
339
+ channel = await transport._connection.createChannel();
340
+ transport.queueChannel = channel;
341
+ console.log(`[QueueManager] DEBUG: Channel recreated after channel closed error for ${queueName}`);
342
+ } catch (recreateErr) {
343
+ throw new Error(`Channel closed during assertQueue for ${queueName} and failed to recreate: ${recreateErr.message}`);
344
+ }
345
+ // Retry assertQueue with new channel (but only if it's not 406)
346
+ if (assertErr.code !== 406) {
347
+ throw new Error(`Failed to create business queue ${queueName}: ${assertErr.message}`);
348
+ }
349
+ } else {
350
+ // Other error - critical, cannot continue
351
+ throw new Error(`Failed to create business queue ${queueName}: ${assertErr.message}`);
352
+ }
334
353
  }
335
354
  }
355
+
356
+ // Verify queue was created/confirmed
357
+ if (!queueCreated) {
358
+ throw new Error(`Failed to create or confirm business queue ${queueName}`);
359
+ }
336
360
  }
337
361
 
338
362
  // Setup DLQ exchange and bindings