@onlineapps/conn-infra-mq 1.1.16 → 1.1.18

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.16",
3
+ "version": "1.1.18",
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": {
@@ -82,43 +82,55 @@ class QueueManager {
82
82
  // Track managed queue
83
83
  this.managedQueues.add(queueName);
84
84
 
85
- // Use checkQueue first to avoid 406 PRECONDITION-FAILED closing the channel
86
- // If queue doesn't exist (404), then assertQueue to create it
87
85
  // IMPORTANT: Check if channel is still open before operations
88
86
  if (!channel || channel.closed) {
89
87
  throw new Error('Channel is closed - cannot ensure queue');
90
88
  }
91
89
 
90
+ // CRITICAL: amqplib's assertQueue() uses RPC pattern even on regular channels
91
+ // This causes channel closure if reply queue doesn't exist
92
+ // Solution: Use checkQueue to verify existence, and if queue doesn't exist,
93
+ // it will be created automatically on first sendToQueue() with passive: false
94
+ // For now, we'll use checkQueue and let the queue be created lazily on first publish
95
+
92
96
  try {
93
97
  const queueInfo = await channel.checkQueue(queueName);
94
98
  // Queue exists - return queue info
95
99
  return queueInfo;
96
100
  } catch (checkErr) {
97
- // Check if channel is still open before assertQueue
101
+ // Check if channel is still open
98
102
  if (!channel || channel.closed) {
99
- throw new Error('Channel closed during checkQueue - cannot create queue');
103
+ throw new Error('Channel closed during checkQueue - cannot verify queue');
100
104
  }
101
105
 
102
- // If queue doesn't exist (404), create it with provided options
106
+ // If queue doesn't exist (404), we'll let it be created lazily on first publish
107
+ // This avoids RPC reply queue issues with assertQueue()
103
108
  if (checkErr.code === 404) {
104
- try {
105
- return await channel.assertQueue(queueName, queueOptions);
106
- } catch (assertErr) {
107
- // If channel closed during assertQueue, throw descriptive error
108
- if (!channel || channel.closed) {
109
- throw new Error(`Channel closed during assertQueue for ${queueName} - likely due to RPC reply queue issue`);
110
- }
111
- throw assertErr;
112
- }
109
+ // Queue doesn't exist - will be created on first sendToQueue()
110
+ // Return a mock queue info to indicate queue will be created lazily
111
+ console.info(`[QueueManager] Queue ${queueName} doesn't exist - will be created on first publish`);
112
+ return {
113
+ queue: queueName,
114
+ messageCount: 0,
115
+ consumerCount: 0
116
+ };
113
117
  } else {
114
118
  // Other error (including 406) - queue exists with different args
115
119
  // Log warning and return queue info without asserting
116
120
  console.warn(`[QueueManager] Queue ${queueName} exists with different arguments, using as-is:`, checkErr.message);
117
- // Check channel again before checkQueue
121
+ // Try checkQueue again to get queue info (if channel still open)
118
122
  if (!channel || channel.closed) {
119
123
  throw new Error('Channel closed - cannot check queue');
120
124
  }
121
- return channel.checkQueue(queueName);
125
+ try {
126
+ return await channel.checkQueue(queueName);
127
+ } catch (retryErr) {
128
+ // If channel closed, throw descriptive error
129
+ if (!channel || channel.closed) {
130
+ throw new Error('Channel closed during checkQueue retry - RPC reply queue issue detected');
131
+ }
132
+ throw retryErr;
133
+ }
122
134
  }
123
135
  }
124
136
  }
@@ -280,17 +292,46 @@ class QueueManager {
280
292
  * @param {Object} options - Queue options
281
293
  */
282
294
  async createTemporaryQueue(prefix = 'temp', options = {}) {
295
+ const transport = this.client._transport;
296
+ if (!transport || !transport.channel) {
297
+ throw new Error('MQ client not connected');
298
+ }
299
+ // Use queueChannel for queue operations
300
+ const channel = transport.queueChannel || transport.channel;
301
+
283
302
  const queueName = `${prefix}.${Date.now()}.${Math.random().toString(36).substr(2, 9)}`;
284
303
 
285
- await this.ensureQueue(queueName, {
304
+ // For temporary queues (rpc.reply.*), we MUST create them explicitly
305
+ // because they are used immediately for consuming replies
306
+ // Use assertQueue directly on queueChannel to avoid RPC reply queue issues
307
+ const queueOptions = {
286
308
  durable: false,
309
+ exclusive: options.exclusive !== false, // Default to exclusive for temporary queues
287
310
  autoDelete: true,
288
- expires: options.expires || 60000, // 1 minute default
289
- exclusive: options.exclusive || false,
290
- ...options
291
- });
311
+ arguments: {}
312
+ };
313
+
314
+ // Add expires if specified
315
+ if (options.expires) {
316
+ queueOptions.arguments['x-expires'] = options.expires;
317
+ }
292
318
 
293
- return queueName;
319
+ // Check if channel is open before assertQueue
320
+ if (!channel || channel.closed) {
321
+ throw new Error('Channel is closed - cannot create temporary queue');
322
+ }
323
+
324
+ try {
325
+ await channel.assertQueue(queueName, queueOptions);
326
+ this.managedQueues.add(queueName);
327
+ return queueName;
328
+ } catch (assertErr) {
329
+ // If channel closed during assertQueue, throw descriptive error
330
+ if (!channel || channel.closed) {
331
+ throw new Error(`Channel closed during assertQueue for temporary queue ${queueName} - RPC reply queue issue detected`);
332
+ }
333
+ throw assertErr;
334
+ }
294
335
  }
295
336
 
296
337
  /**