@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 +1 -1
- package/src/layers/QueueManager.js +63 -22
package/package.json
CHANGED
|
@@ -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
|
|
101
|
+
// Check if channel is still open
|
|
98
102
|
if (!channel || channel.closed) {
|
|
99
|
-
throw new Error('Channel closed during checkQueue - cannot
|
|
103
|
+
throw new Error('Channel closed during checkQueue - cannot verify queue');
|
|
100
104
|
}
|
|
101
105
|
|
|
102
|
-
// If queue doesn't exist (404),
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
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
|
-
|
|
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
|
/**
|