@onlineapps/conn-infra-mq 1.1.15 → 1.1.17
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
|
@@ -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
|
}
|
|
@@ -188,7 +200,8 @@ class QueueManager {
|
|
|
188
200
|
if (!transport || !transport.channel) {
|
|
189
201
|
throw new Error('MQ client not connected');
|
|
190
202
|
}
|
|
191
|
-
|
|
203
|
+
// Use queueChannel for queue operations to avoid RPC reply queue issues
|
|
204
|
+
const channel = transport.queueChannel || transport.channel;
|
|
192
205
|
|
|
193
206
|
const queues = {};
|
|
194
207
|
|
|
@@ -302,7 +315,8 @@ class QueueManager {
|
|
|
302
315
|
if (!transport || !transport.channel) {
|
|
303
316
|
throw new Error('MQ client not connected');
|
|
304
317
|
}
|
|
305
|
-
|
|
318
|
+
// Use queueChannel for queue operations
|
|
319
|
+
const channel = transport.queueChannel || transport.channel;
|
|
306
320
|
|
|
307
321
|
this.managedQueues.delete(queueName);
|
|
308
322
|
return channel.deleteQueue(queueName, options);
|
|
@@ -354,7 +368,8 @@ class QueueManager {
|
|
|
354
368
|
if (!transport || !transport.channel) {
|
|
355
369
|
throw new Error('MQ client not connected');
|
|
356
370
|
}
|
|
357
|
-
|
|
371
|
+
// Exchange operations can use queueChannel (regular channel) - no RPC issues
|
|
372
|
+
const channel = transport.queueChannel || transport.channel;
|
|
358
373
|
|
|
359
374
|
return channel.assertExchange(exchangeName, type, {
|
|
360
375
|
durable: options.durable !== false,
|
|
@@ -373,7 +388,8 @@ class QueueManager {
|
|
|
373
388
|
if (!transport || !transport.channel) {
|
|
374
389
|
throw new Error('MQ client not connected');
|
|
375
390
|
}
|
|
376
|
-
|
|
391
|
+
// Bind operations can use queueChannel (regular channel) - no RPC issues
|
|
392
|
+
const channel = transport.queueChannel || transport.channel;
|
|
377
393
|
|
|
378
394
|
return channel.bindQueue(queue, exchange, routingKey);
|
|
379
395
|
}
|
|
@@ -38,10 +38,19 @@ class RabbitMQClient extends EventEmitter {
|
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Getter for channel - provides compatibility with QueueManager
|
|
41
|
+
* Returns ConfirmChannel for publish operations
|
|
41
42
|
*/
|
|
42
43
|
get channel() {
|
|
43
44
|
return this._channel;
|
|
44
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Getter for queue channel - regular channel for queue operations
|
|
49
|
+
* Use this for assertQueue, checkQueue to avoid RPC reply queue issues
|
|
50
|
+
*/
|
|
51
|
+
get queueChannel() {
|
|
52
|
+
return this._queueChannel || this._channel; // Fallback to main channel if queueChannel not available
|
|
53
|
+
}
|
|
45
54
|
|
|
46
55
|
/**
|
|
47
56
|
* Connects to RabbitMQ server and creates a confirm channel.
|
|
@@ -95,6 +104,15 @@ class RabbitMQClient extends EventEmitter {
|
|
|
95
104
|
* @returns {Promise<void>}
|
|
96
105
|
*/
|
|
97
106
|
async disconnect() {
|
|
107
|
+
try {
|
|
108
|
+
if (this._queueChannel) {
|
|
109
|
+
await this._queueChannel.close();
|
|
110
|
+
this._queueChannel = null;
|
|
111
|
+
}
|
|
112
|
+
} catch (err) {
|
|
113
|
+
// Log but don't emit - queue channel errors are less critical
|
|
114
|
+
console.warn('[RabbitMQClient] Error closing queue channel:', err.message);
|
|
115
|
+
}
|
|
98
116
|
try {
|
|
99
117
|
if (this._channel) {
|
|
100
118
|
await this._channel.close();
|
|
@@ -134,9 +152,22 @@ class RabbitMQClient extends EventEmitter {
|
|
|
134
152
|
try {
|
|
135
153
|
// Ensure queue exists if publishing directly to queue and using default exchange
|
|
136
154
|
if (!exchange) {
|
|
155
|
+
// Use queueChannel (regular channel) for queue operations to avoid RPC reply queue issues
|
|
137
156
|
// Use central config for infrastructure queues
|
|
138
157
|
const queueOptions = this._getQueueOptions(queue);
|
|
139
|
-
|
|
158
|
+
try {
|
|
159
|
+
await this._queueChannel.checkQueue(queue);
|
|
160
|
+
// Queue exists - proceed to publish
|
|
161
|
+
} catch (checkErr) {
|
|
162
|
+
// If queue doesn't exist (404), create it
|
|
163
|
+
if (checkErr.code === 404) {
|
|
164
|
+
await this._queueChannel.assertQueue(queue, queueOptions);
|
|
165
|
+
} else {
|
|
166
|
+
// Other error (including 406) - queue exists with different args, proceed
|
|
167
|
+
console.warn(`[RabbitMQClient] Queue ${queue} exists with different arguments, using as-is`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Publish using ConfirmChannel (for publisher confirms)
|
|
140
171
|
this._channel.sendToQueue(queue, buffer, { persistent, headers, routingKey });
|
|
141
172
|
} else {
|
|
142
173
|
// If exchange is specified, assert exchange and publish to it
|
|
@@ -177,9 +208,10 @@ class RabbitMQClient extends EventEmitter {
|
|
|
177
208
|
|
|
178
209
|
if (isInfraQueue) {
|
|
179
210
|
// Infrastructure queue - should already exist, created by infrastructure initialization
|
|
211
|
+
// Use queueChannel (regular channel) for queue operations to avoid RPC reply queue issues
|
|
180
212
|
// Only check if it exists, don't try to create or assert with arguments
|
|
181
213
|
try {
|
|
182
|
-
await this.
|
|
214
|
+
await this._queueChannel.checkQueue(queue);
|
|
183
215
|
// Queue exists - proceed to consume
|
|
184
216
|
} catch (checkErr) {
|
|
185
217
|
if (checkErr.code === 404) {
|
|
@@ -191,13 +223,14 @@ class RabbitMQClient extends EventEmitter {
|
|
|
191
223
|
}
|
|
192
224
|
} else {
|
|
193
225
|
// Business queue - may need to be created, but use unified config
|
|
226
|
+
// Use queueChannel (regular channel) for queue operations to avoid RPC reply queue issues
|
|
194
227
|
const queueOptions = this._getQueueOptions(queue, { durable });
|
|
195
228
|
|
|
196
229
|
// Try to assert queue with our config
|
|
197
230
|
// If it fails with 406 (PRECONDITION-FAILED), queue exists with different args - use it as-is
|
|
198
231
|
// IMPORTANT: Don't try to re-assert after 406, as it will close the channel
|
|
199
232
|
try {
|
|
200
|
-
await this.
|
|
233
|
+
await this._queueChannel.assertQueue(queue, queueOptions);
|
|
201
234
|
} catch (assertErr) {
|
|
202
235
|
// If queue exists with different arguments (406), use it as-is without re-asserting
|
|
203
236
|
if (assertErr.code === 406) {
|