@onlineapps/conn-infra-mq 1.1.29 → 1.1.31

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.29",
3
+ "version": "1.1.31",
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,12 +294,16 @@ 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, and continue
298
299
  try {
299
300
  // Check if channel is still open before each operation
300
301
  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`);
302
+ console.error(`[QueueManager] DEBUG: Channel closed before creating ${queueName}, recreating...`);
303
+ // Recreate channel if closed
304
+ channel = await transport._connection.createChannel();
305
+ transport.queueChannel = channel;
306
+ console.log(`[QueueManager] DEBUG: Channel recreated for ${queueName}`);
303
307
  }
304
308
 
305
309
  console.log(`[QueueManager] DEBUG: About to assertQueue ${queueName} with options:`, JSON.stringify(queueOptions, null, 2));
@@ -313,22 +317,36 @@ class QueueManager {
313
317
  } catch (assertErr) {
314
318
  console.error(`[QueueManager] DEBUG: assertQueue failed for ${queueName}:`, assertErr.message);
315
319
  console.error(`[QueueManager] DEBUG: Error code: ${assertErr.code}, channel closed: ${channel ? channel.closed : 'N/A'}`);
316
- console.error(`[QueueManager] DEBUG: Stack trace:`, assertErr.stack);
317
320
 
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
321
+ // If 406 PRECONDITION-FAILED, queue exists with different args - channel is closed, recreate it
322
+ // CRITICAL: amqplib closes channel on 406, so we MUST recreate it to continue
327
323
  if (assertErr.code === 406) {
328
- console.warn(`[QueueManager] Queue ${queueName} exists with different arguments, using as-is:`, assertErr.message);
324
+ console.warn(`[QueueManager] Queue ${queueName} exists with different arguments (406), channel closed. Recreating channel...`);
325
+
326
+ // Recreate channel - 406 closes it
327
+ try {
328
+ channel = await transport._connection.createChannel();
329
+ transport.queueChannel = channel;
330
+ console.log(`[QueueManager] DEBUG: Channel recreated after 406 for ${queueName}, channel closed=${channel.closed}`);
331
+ } catch (recreateErr) {
332
+ throw new Error(`Failed to recreate channel after 406 for ${queueName}: ${recreateErr.message}`);
333
+ }
334
+
329
335
  // Queue exists (just with different args) - accept it
330
336
  queues[queueInfo.type] = queueName;
331
337
  } else {
338
+ // Other error - check if channel closed
339
+ if (!channel || channel.closed) {
340
+ console.error(`[QueueManager] DEBUG: Channel was closed during assertQueue for ${queueName}`);
341
+ // Try to recreate channel
342
+ try {
343
+ channel = await transport._connection.createChannel();
344
+ transport.queueChannel = channel;
345
+ console.log(`[QueueManager] DEBUG: Channel recreated after error for ${queueName}`);
346
+ } catch (recreateErr) {
347
+ throw new Error(`Channel closed during assertQueue for ${queueName} and failed to recreate: ${recreateErr.message}`);
348
+ }
349
+ }
332
350
  // Other error - critical, cannot continue
333
351
  throw new Error(`Failed to create business queue ${queueName}: ${assertErr.message}`);
334
352
  }
@@ -336,25 +354,62 @@ class QueueManager {
336
354
  }
337
355
 
338
356
  // Setup DLQ exchange and bindings
339
- await channel.assertExchange(this.config.dlxExchange, 'direct', {
340
- durable: true
341
- });
357
+ console.log(`[QueueManager] DEBUG: Setting up DLQ exchange: ${this.config.dlxExchange}`);
358
+ console.log(`[QueueManager] DEBUG: Channel state before assertExchange: closed=${channel.closed}`);
359
+
360
+ try {
361
+ await channel.assertExchange(this.config.dlxExchange, 'direct', {
362
+ durable: true
363
+ });
364
+ console.log(`[QueueManager] DEBUG: DLQ exchange asserted, channel closed=${channel.closed}`);
365
+ } catch (exErr) {
366
+ console.error(`[QueueManager] DEBUG: assertExchange failed:`, exErr.message);
367
+ if (!channel || channel.closed) {
368
+ throw new Error(`Channel closed during assertExchange for ${this.config.dlxExchange}`);
369
+ }
370
+ throw exErr;
371
+ }
342
372
 
343
373
  // Bind DLQ
344
- await channel.bindQueue(
345
- queues.dlq,
346
- this.config.dlxExchange,
347
- `${serviceName}.queue.dlq`
348
- );
349
-
350
- if (queues.workflow) {
374
+ console.log(`[QueueManager] DEBUG: Binding DLQ: ${queues.dlq} to ${this.config.dlxExchange}`);
375
+ console.log(`[QueueManager] DEBUG: Channel state before bindQueue: closed=${channel.closed}`);
376
+
377
+ try {
351
378
  await channel.bindQueue(
352
379
  queues.dlq,
353
380
  this.config.dlxExchange,
354
- `${serviceName}.workflow.dlq`
381
+ `${serviceName}.queue.dlq`
355
382
  );
383
+ console.log(`[QueueManager] DEBUG: DLQ bound, channel closed=${channel.closed}`);
384
+ } catch (bindErr) {
385
+ console.error(`[QueueManager] DEBUG: bindQueue failed:`, bindErr.message);
386
+ if (!channel || channel.closed) {
387
+ throw new Error(`Channel closed during bindQueue for ${queues.dlq}`);
388
+ }
389
+ throw bindErr;
390
+ }
391
+
392
+ if (queues.workflow) {
393
+ console.log(`[QueueManager] DEBUG: Binding workflow DLQ: ${queues.dlq} to ${this.config.dlxExchange}`);
394
+ console.log(`[QueueManager] DEBUG: Channel state before workflow bindQueue: closed=${channel.closed}`);
395
+
396
+ try {
397
+ await channel.bindQueue(
398
+ queues.dlq,
399
+ this.config.dlxExchange,
400
+ `${serviceName}.workflow.dlq`
401
+ );
402
+ console.log(`[QueueManager] DEBUG: Workflow DLQ bound, channel closed=${channel.closed}`);
403
+ } catch (bindErr) {
404
+ console.error(`[QueueManager] DEBUG: workflow bindQueue failed:`, bindErr.message);
405
+ if (!channel || channel.closed) {
406
+ throw new Error(`Channel closed during workflow bindQueue`);
407
+ }
408
+ throw bindErr;
409
+ }
356
410
  }
357
411
 
412
+ console.log(`[QueueManager] DEBUG: setupServiceQueues completed successfully, channel closed=${channel.closed}`);
358
413
  return queues;
359
414
  }
360
415