@onlineapps/conn-infra-mq 1.1.41 → 1.1.42
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
|
@@ -114,6 +114,40 @@ class RabbitMQClient extends EventEmitter {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Recreates the publish channel if it's closed.
|
|
119
|
+
* Used when channel closes unexpectedly (e.g., due to 406 errors).
|
|
120
|
+
* @private
|
|
121
|
+
* @returns {Promise<void>}
|
|
122
|
+
* @throws {Error} If connection is not available or channel recreation fails.
|
|
123
|
+
*/
|
|
124
|
+
async _recreateChannel() {
|
|
125
|
+
if (!this._connection) {
|
|
126
|
+
throw new Error('Cannot recreate channel: connection is not available');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// Close old channel if it exists
|
|
131
|
+
if (this._channel) {
|
|
132
|
+
try {
|
|
133
|
+
await this._channel.close();
|
|
134
|
+
} catch (err) {
|
|
135
|
+
// Ignore errors when closing already-closed channel
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create new ConfirmChannel
|
|
140
|
+
this._channel = await this._connection.createConfirmChannel();
|
|
141
|
+
this._channel.on('error', (err) => this.emit('error', err));
|
|
142
|
+
this._channel.on('close', () => {
|
|
143
|
+
this.emit('error', new Error('RabbitMQ channel closed unexpectedly'));
|
|
144
|
+
});
|
|
145
|
+
} catch (err) {
|
|
146
|
+
this._channel = null;
|
|
147
|
+
throw new Error(`Failed to recreate channel: ${err.message}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
117
151
|
/**
|
|
118
152
|
* Disconnects: closes channel and connection.
|
|
119
153
|
* @returns {Promise<void>}
|
|
@@ -158,6 +192,16 @@ class RabbitMQClient extends EventEmitter {
|
|
|
158
192
|
if (!this._channel) {
|
|
159
193
|
throw new Error('Cannot publish: channel is not initialized');
|
|
160
194
|
}
|
|
195
|
+
|
|
196
|
+
// Check if channel is closed and recreate if needed
|
|
197
|
+
if (this._channel.closed) {
|
|
198
|
+
console.warn('[RabbitMQClient] Publish channel is closed, recreating...');
|
|
199
|
+
try {
|
|
200
|
+
await this._recreateChannel();
|
|
201
|
+
} catch (recreateErr) {
|
|
202
|
+
throw new Error(`Cannot publish: channel is closed and recreation failed: ${recreateErr.message}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
161
205
|
|
|
162
206
|
const exchange = this._config.exchange || '';
|
|
163
207
|
const routingKey = options.routingKey || queue;
|
|
@@ -177,19 +221,47 @@ class RabbitMQClient extends EventEmitter {
|
|
|
177
221
|
// Business queue - should already exist, skip checkQueue() to avoid channel closure
|
|
178
222
|
console.log(`[RabbitMQClient] DEBUG: Business queue ${queue}, skipping checkQueue() in publish() - queue should already exist`);
|
|
179
223
|
} else {
|
|
180
|
-
// Infrastructure queue -
|
|
224
|
+
// Infrastructure queue - use assertQueue() directly (idempotent, won't cause 406)
|
|
225
|
+
// assertQueue() will use existing queue even if args differ, avoiding channel closure
|
|
226
|
+
// Recreate queueChannel if it's closed
|
|
227
|
+
if (!this._queueChannel || this._queueChannel.closed) {
|
|
228
|
+
if (!this._connection) {
|
|
229
|
+
throw new Error('Cannot assertQueue: connection is not available');
|
|
230
|
+
}
|
|
231
|
+
console.warn('[RabbitMQClient] Queue channel is closed, recreating...');
|
|
232
|
+
try {
|
|
233
|
+
if (this._queueChannel) {
|
|
234
|
+
try {
|
|
235
|
+
await this._queueChannel.close();
|
|
236
|
+
} catch (err) {
|
|
237
|
+
// Ignore errors when closing already-closed channel
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
this._queueChannel = await this._connection.createChannel();
|
|
241
|
+
this._queueChannel._createdAt = new Date().toISOString();
|
|
242
|
+
this._queueChannel._closeReason = null;
|
|
243
|
+
this._queueChannel._lastOperation = null;
|
|
244
|
+
this._queueChannel.on('error', (err) => {
|
|
245
|
+
console.error('[RabbitMQClient] Queue channel error:', err.message);
|
|
246
|
+
this._queueChannel._closeReason = `Error: ${err.message} (code: ${err.code})`;
|
|
247
|
+
});
|
|
248
|
+
this._queueChannel.on('close', () => {
|
|
249
|
+
console.error('[RabbitMQClient] Queue channel closed');
|
|
250
|
+
});
|
|
251
|
+
} catch (recreateErr) {
|
|
252
|
+
console.warn(`[RabbitMQClient] Failed to recreate queue channel, proceeding anyway:`, recreateErr.message);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
181
256
|
const queueOptions = this._getQueueOptions(queue);
|
|
182
257
|
try {
|
|
183
|
-
|
|
184
|
-
// Queue exists - proceed to publish
|
|
185
|
-
} catch (checkErr) {
|
|
186
|
-
// If queue doesn't exist (404), create it
|
|
187
|
-
if (checkErr.code === 404) {
|
|
258
|
+
if (this._queueChannel && !this._queueChannel.closed) {
|
|
188
259
|
await this._queueChannel.assertQueue(queue, queueOptions);
|
|
189
|
-
} else {
|
|
190
|
-
// Other error (including 406) - queue exists with different args, proceed
|
|
191
|
-
console.warn(`[RabbitMQClient] Queue ${queue} exists with different arguments, using as-is`);
|
|
192
260
|
}
|
|
261
|
+
} catch (assertErr) {
|
|
262
|
+
// If assertQueue fails (shouldn't happen), log and proceed anyway
|
|
263
|
+
// The queue likely exists with different args - publish will work or fail clearly
|
|
264
|
+
console.warn(`[RabbitMQClient] assertQueue failed for ${queue}, proceeding anyway:`, assertErr.message);
|
|
193
265
|
}
|
|
194
266
|
}
|
|
195
267
|
// Publish using ConfirmChannel (for publisher confirms)
|