@onlineapps/conn-infra-mq 1.1.47 → 1.1.49

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.47",
3
+ "version": "1.1.49",
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": {
@@ -209,6 +209,12 @@ class QueueManager {
209
209
  * @param {Object} options - Configuration options
210
210
  */
211
211
  async setupServiceQueues(serviceName, options = {}) {
212
+ const setupStartTime = Date.now();
213
+ const setupStartTimeISO = new Date().toISOString();
214
+
215
+ console.log(`[QueueManager] [SETUP] Starting setupServiceQueues() for service: ${serviceName} at ${setupStartTimeISO}`);
216
+ console.log(`[QueueManager] [SETUP] Options:`, JSON.stringify(options));
217
+
212
218
  const transport = this.client._transport;
213
219
  if (!transport || !transport.channel) {
214
220
  throw new Error('MQ client not connected');
@@ -218,6 +224,9 @@ class QueueManager {
218
224
  // If channel is closed, we cannot continue - this is a critical error
219
225
  let channel = transport.queueChannel || transport.channel;
220
226
 
227
+ console.log(`[QueueManager] [SETUP] Channel state: exists=${!!channel}, closed=${channel ? channel.closed : 'N/A'}`);
228
+ console.log(`[QueueManager] [SETUP] QueueChannel exists: ${!!transport.queueChannel}, MainChannel exists: ${!!transport.channel}`);
229
+
221
230
  if (!channel || channel.closed) {
222
231
  throw new Error('Queue channel is not available or closed - cannot create business queues');
223
232
  }
@@ -231,6 +240,8 @@ class QueueManager {
231
240
  if (options.includeWorkflow !== false) {
232
241
  queueNames.push({ name: `${serviceName}.workflow`, type: 'workflow' });
233
242
  }
243
+
244
+ console.log(`[QueueManager] [SETUP] Will create ${queueNames.length} queues:`, queueNames.map(q => q.name).join(', '));
234
245
 
235
246
  // CRITICAL: Create ALL queues using assertQueue directly (no checkQueue first to avoid channel closure)
236
247
  // This ensures all queues are created atomically
@@ -384,9 +395,13 @@ class QueueManager {
384
395
  let queueCreated = false;
385
396
 
386
397
  try {
387
- console.log(`[QueueManager] DEBUG: About to assertQueue ${queueName} with correct arguments`);
388
- console.log(`[QueueManager] DEBUG: Channel state: exists=${!!channel}, closed=${channel ? (channel.closed === true ? 'true' : channel.closed === false ? 'false' : 'undefined') : 'N/A'}`);
389
- console.log(`[QueueManager] DEBUG: Queue options:`, JSON.stringify(queueOptions));
398
+ const assertStartTime = Date.now();
399
+ console.log(`[QueueManager] [QUEUE] Starting assertQueue for: ${queueName} at ${new Date().toISOString()}`);
400
+ console.log(`[QueueManager] [QUEUE] Queue type: ${queueInfo.type}`);
401
+ console.log(`[QueueManager] [QUEUE] Channel state: exists=${!!channel}, closed=${channel ? (channel.closed === true ? 'true' : channel.closed === false ? 'false' : 'undefined') : 'N/A'}`);
402
+ console.log(`[QueueManager] [QUEUE] Channel created at: ${channel._createdAt || 'N/A'}`);
403
+ console.log(`[QueueManager] [QUEUE] Channel last operation: ${channel._lastOperation || 'N/A'}`);
404
+ console.log(`[QueueManager] [QUEUE] Queue options:`, JSON.stringify(queueOptions, null, 2));
390
405
 
391
406
  // CRITICAL: Use assertQueue() DIRECTLY - it's idempotent
392
407
  // If queue doesn't exist → creates it
@@ -394,8 +409,10 @@ class QueueManager {
394
409
  // If queue exists with different params → 406, channel closes (should not happen now, but handle it)
395
410
  await channel.assertQueue(queueName, queueOptions);
396
411
 
412
+ const assertEndTime = Date.now();
397
413
  // Queue created or already exists with same params
398
- console.log(`[QueueManager] DEBUG: assertQueue succeeded for ${queueName}`);
414
+ console.log(`[QueueManager] [QUEUE] assertQueue succeeded for ${queueName} (took ${assertEndTime - assertStartTime}ms)`);
415
+ console.log(`[QueueManager] [QUEUE] Queue created/verified at: ${new Date().toISOString()}`);
399
416
  if (channel && channel._lastOperation !== undefined) {
400
417
  channel._lastOperation = `assertQueue ${queueName} succeeded`;
401
418
  }
@@ -528,6 +545,10 @@ class QueueManager {
528
545
  }
529
546
  }
530
547
 
548
+ const setupEndTime = Date.now();
549
+ console.log(`[QueueManager] [SETUP] ✓ setupServiceQueues completed successfully at ${new Date().toISOString()} (total time: ${setupEndTime - setupStartTime}ms)`);
550
+ console.log(`[QueueManager] [SETUP] Created queues:`, Object.keys(queues).map(k => `${k}=${queues[k]}`).join(', '));
551
+ console.log(`[QueueManager] [SETUP] Channel state after setup: closed=${channel ? channel.closed : 'N/A'}`);
531
552
  console.log(`[QueueManager] DEBUG: setupServiceQueues completed successfully, channel closed=${channel.closed}`);
532
553
  return queues;
533
554
  }
@@ -68,22 +68,39 @@ class RabbitMQClient extends EventEmitter {
68
68
 
69
69
  // Use ConfirmChannel to enable publisher confirms for publish operations
70
70
  // BUT: Create a separate regular channel for queue operations to avoid RPC reply queue issues
71
+ const channelStartTime = Date.now();
71
72
  this._channel = await this._connection.createConfirmChannel();
72
- this._channel.on('error', (err) => this.emit('error', err));
73
+ const channelEndTime = Date.now();
74
+ const channelCreatedAt = new Date().toISOString();
75
+
76
+ console.log(`[RabbitMQClient] [CHANNEL] Created ConfirmChannel at ${channelCreatedAt} (took ${channelEndTime - channelStartTime}ms)`);
77
+ console.log(`[RabbitMQClient] [CHANNEL] ConfirmChannel state: closed=${this._channel.closed}`);
78
+
79
+ this._channel.on('error', (err) => {
80
+ console.error(`[RabbitMQClient] [CHANNEL] ConfirmChannel error at ${new Date().toISOString()}:`, err.message, err.code);
81
+ this.emit('error', err);
82
+ });
73
83
  this._channel.on('close', () => {
84
+ console.error(`[RabbitMQClient] [CHANNEL] ConfirmChannel closed at ${new Date().toISOString()}`);
85
+ console.error(`[RabbitMQClient] [CHANNEL] Channel was created at: ${channelCreatedAt}`);
74
86
  // Emit a channel close error
75
87
  this.emit('error', new Error('RabbitMQ channel closed unexpectedly'));
76
88
  });
77
89
 
78
90
  // Create a separate regular channel for queue operations (assertQueue, checkQueue)
79
91
  // This avoids RPC reply queue issues with ConfirmChannel.assertQueue()
92
+ const queueChannelStartTime = Date.now();
80
93
  this._queueChannel = await this._connection.createChannel();
94
+ const queueChannelEndTime = Date.now();
81
95
 
82
96
  // CRITICAL: Track channel state and close reason
83
97
  this._queueChannel._createdAt = new Date().toISOString();
84
98
  this._queueChannel._closeReason = null;
85
99
  this._queueChannel._lastOperation = null;
86
100
 
101
+ console.log(`[RabbitMQClient] [CHANNEL] Created queueChannel at ${this._queueChannel._createdAt} (took ${queueChannelEndTime - queueChannelStartTime}ms)`);
102
+ console.log(`[RabbitMQClient] [CHANNEL] QueueChannel state: closed=${this._queueChannel.closed}, connection=${this._connection ? 'connected' : 'null'}`);
103
+
87
104
  this._queueChannel.on('error', (err) => {
88
105
  // Log but don't emit - queue channel errors are less critical
89
106
  console.error('[RabbitMQClient] Queue channel error:', err.message);
@@ -282,22 +299,10 @@ class RabbitMQClient extends EventEmitter {
282
299
 
283
300
  if (isInfraQueue) {
284
301
  // Infrastructure queue - should already exist, created by infrastructure initialization
285
- // Use queueChannel (regular channel) for queue operations to avoid RPC reply queue issues
286
- // Only check if it exists, don't try to create or assert with arguments
287
- console.log(`[RabbitMQClient] DEBUG: Infrastructure queue ${queue}, checking existence...`);
288
- try {
289
- await this._queueChannel.checkQueue(queue);
290
- console.log(`[RabbitMQClient] DEBUG: Infrastructure queue ${queue} exists`);
291
- // Queue exists - proceed to consume
292
- } catch (checkErr) {
293
- console.error(`[RabbitMQClient] DEBUG: checkQueue failed for infrastructure queue ${queue}:`, checkErr.message);
294
- if (checkErr.code === 404) {
295
- // Queue doesn't exist - infrastructure problem
296
- throw new Error(`Infrastructure queue '${queue}' not found. Queue should be created during infrastructure initialization.`);
297
- }
298
- // Other error - rethrow
299
- throw checkErr;
300
- }
302
+ // CRITICAL: Do NOT use checkQueue() - it closes channel on 406 if queue exists with different args
303
+ // Just proceed to consume() - if queue doesn't exist, consume() will fail with clear error
304
+ // This avoids channel closure from checkQueue() on infrastructure queues
305
+ console.log(`[RabbitMQClient] DEBUG: Infrastructure queue ${queue}, skipping checkQueue() - queue should already exist (created by infrastructure initialization)`);
301
306
  } else {
302
307
  // Business queue - should already be created by setupServiceQueues() BEFORE consume is called
303
308
  // CRITICAL: Do NOT use checkQueue() - it closes channel on 404!
@@ -312,10 +317,16 @@ class RabbitMQClient extends EventEmitter {
312
317
  this._channel.prefetch(prefetch);
313
318
  }
314
319
 
315
- await this._channel.consume(
320
+ const consumeStartTime = Date.now();
321
+ console.log(`[RabbitMQClient] [CONSUMER] Starting consume() for queue: ${queue} at ${new Date().toISOString()}`);
322
+ console.log(`[RabbitMQClient] [CONSUMER] Options: prefetch=${prefetch}, noAck=${noAck}, durable=${durable}`);
323
+ console.log(`[RabbitMQClient] [CONSUMER] Channel state before consume: closed=${this._channel.closed}`);
324
+
325
+ const consumeResult = await this._channel.consume(
316
326
  queue,
317
327
  async (msg) => {
318
328
  if (msg === null) {
329
+ console.log(`[RabbitMQClient] [CONSUMER] Received null message (queue ${queue} was deleted or connection closed)`);
319
330
  return;
320
331
  }
321
332
  try {
@@ -324,12 +335,31 @@ class RabbitMQClient extends EventEmitter {
324
335
  this._channel.ack(msg);
325
336
  }
326
337
  } catch (handlerErr) {
338
+ console.error(`[RabbitMQClient] [CONSUMER] Error processing message from ${queue}:`, handlerErr.message);
327
339
  // Negative acknowledge and requeue by default
328
340
  this._channel.nack(msg, false, true);
329
341
  }
330
342
  },
331
343
  { noAck }
332
344
  );
345
+
346
+ const consumeEndTime = Date.now();
347
+ const consumerTag = consumeResult.consumerTag;
348
+ console.log(`[RabbitMQClient] [CONSUMER] ✓ Consumer created for queue: ${queue} at ${new Date().toISOString()} (took ${consumeEndTime - consumeStartTime}ms)`);
349
+ console.log(`[RabbitMQClient] [CONSUMER] ConsumerTag: ${consumerTag}`);
350
+ console.log(`[RabbitMQClient] [CONSUMER] Channel state after consume: closed=${this._channel.closed}`);
351
+
352
+ // Store consumerTag for cleanup tracking
353
+ if (!this._consumers) {
354
+ this._consumers = new Map();
355
+ }
356
+ this._consumers.set(queue, {
357
+ consumerTag,
358
+ createdAt: new Date().toISOString(),
359
+ queue,
360
+ prefetch,
361
+ noAck
362
+ });
333
363
  } catch (err) {
334
364
  this.emit('error', err);
335
365
  throw err;