@autofleet/rabbit 3.3.0-beta.11 → 3.3.0-beta.3
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/.nvmrc +1 -1
- package/dist/index.d.ts +13 -35
- package/dist/index.js +119 -486
- package/dist/lib/consts.d.ts +4 -2
- package/dist/lib/consts.js +6 -3
- package/dist/lib/types.d.ts +8 -1
- package/package.json +1 -1
- package/src/index.ts +153 -585
- package/src/lib/consts.ts +5 -2
- package/src/lib/types.ts +9 -2
package/dist/index.js
CHANGED
|
@@ -56,57 +56,10 @@ class RabbitMq {
|
|
|
56
56
|
},
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
-
constructor(options
|
|
59
|
+
constructor(options, redisConfig) {
|
|
60
60
|
this.DISCONNECT_MSG = 'rabbit: connection disconnect';
|
|
61
61
|
this.RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
|
|
62
62
|
this.consumers = [];
|
|
63
|
-
this.doesVHostExist = false;
|
|
64
|
-
this.vhost = 'quorum-vhost';
|
|
65
|
-
this.oldConsumers = [];
|
|
66
|
-
this.assertVHost = async () => {
|
|
67
|
-
if (this.doesVHostExist) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
const username = process.env.RABBITMQ_USERNAME || 'guest';
|
|
71
|
-
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
72
|
-
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
|
|
73
|
-
const headers = {
|
|
74
|
-
Authorization: `Basic ${credentials}`,
|
|
75
|
-
'Content-Type': 'application/json',
|
|
76
|
-
};
|
|
77
|
-
const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;
|
|
78
|
-
const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;
|
|
79
|
-
try {
|
|
80
|
-
const response = await fetch(url, {
|
|
81
|
-
method: 'GET',
|
|
82
|
-
headers,
|
|
83
|
-
});
|
|
84
|
-
if (response.status === 200) {
|
|
85
|
-
this.doesVHostExist = true;
|
|
86
|
-
logger_1.default.info('Vhost exists', { vhost: this.vhost });
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (response.status !== 404) {
|
|
90
|
-
logger_1.default.error('Failed to check vhost', { response });
|
|
91
|
-
throw new rabbitError_1.default('Failed to check vhost');
|
|
92
|
-
}
|
|
93
|
-
const createResponse = await fetch(url, {
|
|
94
|
-
method: 'PUT',
|
|
95
|
-
headers,
|
|
96
|
-
body: JSON.stringify({ default_queue_type: 'quorum' }),
|
|
97
|
-
});
|
|
98
|
-
if (!createResponse.ok) {
|
|
99
|
-
logger_1.default.error('Failed to create vhost', { response: createResponse });
|
|
100
|
-
throw new rabbitError_1.default('Failed to create vhost');
|
|
101
|
-
}
|
|
102
|
-
this.doesVHostExist = true;
|
|
103
|
-
logger_1.default.info('Vhost created', { vhost: this.vhost });
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
logger_1.default.error('Failed to check or create vhost', { error });
|
|
107
|
-
throw error;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
63
|
this.shouldConsumeMessageByTimestamp = async (msg) => {
|
|
111
64
|
if (msg) {
|
|
112
65
|
const { properties: { headers } } = msg;
|
|
@@ -164,10 +117,24 @@ class RabbitMq {
|
|
|
164
117
|
}
|
|
165
118
|
};
|
|
166
119
|
this.em = new events_1.EventEmitter();
|
|
167
|
-
this.
|
|
120
|
+
this.publishChannel = null;
|
|
168
121
|
this.publishChannelSetupPromise = null;
|
|
169
|
-
this.
|
|
170
|
-
|
|
122
|
+
this.connectionsMap = {
|
|
123
|
+
[consts_1.ConnectionPurpose.Consume]: {
|
|
124
|
+
connection: null,
|
|
125
|
+
creatingConnection: false,
|
|
126
|
+
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
127
|
+
connectionFailedEventName: 'consumeConnectionFailed',
|
|
128
|
+
blockReconnect: false,
|
|
129
|
+
},
|
|
130
|
+
[consts_1.ConnectionPurpose.Publish]: {
|
|
131
|
+
connection: null,
|
|
132
|
+
creatingConnection: false,
|
|
133
|
+
connectionCreatedEventName: 'publishConnectionCreated',
|
|
134
|
+
connectionFailedEventName: 'publishConnectionFailed',
|
|
135
|
+
blockReconnect: false,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
171
138
|
this.exchanges = {};
|
|
172
139
|
this.queues = {};
|
|
173
140
|
this.queueSetupPromises = {};
|
|
@@ -188,43 +155,32 @@ class RabbitMq {
|
|
|
188
155
|
await this.gracefulShutdown('SIGINT');
|
|
189
156
|
});
|
|
190
157
|
}
|
|
191
|
-
// TODO: [QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers
|
|
192
|
-
this.oldEm = new events_1.EventEmitter();
|
|
193
|
-
this.oldChannel = null;
|
|
194
|
-
this.oldPublishChannelSetupPromise = null;
|
|
195
|
-
this.oldConnection = null;
|
|
196
|
-
this.oldCreatingConnection = false;
|
|
197
|
-
this.oldExchanges = {};
|
|
198
|
-
this.oldQueues = {};
|
|
199
|
-
this.oldQueueSetupPromises = {};
|
|
200
|
-
this.oldAssertExchangePromises = {};
|
|
201
|
-
this.oldConsumers = [];
|
|
202
|
-
this.oldConsumersTags = [];
|
|
203
158
|
}
|
|
204
|
-
async getConnection() {
|
|
159
|
+
async getConnection(connectionPurpose) {
|
|
205
160
|
return new Promise(async (resolve, reject) => {
|
|
206
|
-
|
|
161
|
+
const { connection, creatingConnection, connectionCreatedEventName, connectionFailedEventName, blockReconnect, } = this.connectionsMap[connectionPurpose];
|
|
162
|
+
if (blockReconnect) {
|
|
207
163
|
debug('rabbit: block reconnect');
|
|
208
164
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
209
165
|
// @ts-ignore
|
|
210
166
|
return resolve();
|
|
211
167
|
}
|
|
212
|
-
if (
|
|
213
|
-
if (this.options?.disableReconnect ||
|
|
168
|
+
if (connection !== null) {
|
|
169
|
+
if (this.options?.disableReconnect || connection?.isConnected()) {
|
|
214
170
|
debug('rabbit: connection - is connected');
|
|
215
171
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
216
172
|
// @ts-ignore
|
|
217
|
-
return resolve(
|
|
173
|
+
return resolve(connection);
|
|
218
174
|
}
|
|
219
175
|
debug('rabbit: connection - reconnecting');
|
|
220
176
|
}
|
|
221
|
-
if (
|
|
177
|
+
if (creatingConnection) {
|
|
222
178
|
debug('rabbit: creating connection emi');
|
|
223
|
-
this.em.once(
|
|
224
|
-
this.em.once(
|
|
179
|
+
this.em.once(connectionCreatedEventName, resolve);
|
|
180
|
+
this.em.once(connectionFailedEventName, reject);
|
|
225
181
|
return;
|
|
226
182
|
}
|
|
227
|
-
this.creatingConnection = true;
|
|
183
|
+
this.connectionsMap[connectionPurpose].creatingConnection = true;
|
|
228
184
|
let isResolved = false;
|
|
229
185
|
// It is import to use it as a function and not as a variable
|
|
230
186
|
// because of k8s changes the env variables
|
|
@@ -234,60 +190,62 @@ class RabbitMq {
|
|
|
234
190
|
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
235
191
|
const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';
|
|
236
192
|
debug('rabbit: creating connection', { host, userName, HEARTBEAT });
|
|
237
|
-
return [`amqp://${userName}:${password}@${host}
|
|
193
|
+
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
238
194
|
};
|
|
239
195
|
const defaultUrls = findServers();
|
|
240
|
-
const
|
|
196
|
+
const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
241
197
|
findServers,
|
|
242
198
|
});
|
|
243
|
-
this.connection =
|
|
244
|
-
|
|
199
|
+
this.connectionsMap[connectionPurpose].connection = newConnection;
|
|
200
|
+
logger_1.default.info(`rabbit: created new connection ${connectionPurpose}`);
|
|
201
|
+
newConnection.on('error', (err) => {
|
|
245
202
|
logger_1.default.error('rabbit: connection error', { err });
|
|
246
203
|
if (!isResolved) {
|
|
247
204
|
isResolved = true;
|
|
248
205
|
reject(err);
|
|
249
|
-
this.em.emit(
|
|
206
|
+
this.em.emit(connectionFailedEventName, err);
|
|
250
207
|
}
|
|
251
208
|
});
|
|
252
|
-
|
|
209
|
+
newConnection.on('connectFailed', (err) => {
|
|
253
210
|
this.consumersTags = [];
|
|
254
|
-
logger_1.default.error('rabbit: connection connectFailed', { err
|
|
211
|
+
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
255
212
|
if (!isResolved) {
|
|
256
213
|
isResolved = true;
|
|
257
214
|
reject(err);
|
|
258
|
-
this.em.emit(
|
|
215
|
+
this.em.emit(connectionFailedEventName, err);
|
|
259
216
|
}
|
|
260
217
|
});
|
|
261
|
-
|
|
262
|
-
// this.channel = null;
|
|
218
|
+
newConnection.on('disconnect', ({ err }) => {
|
|
263
219
|
this.consumersTags = [];
|
|
264
220
|
debug('rabbit: connection closed');
|
|
265
221
|
if (this.options?.disableReconnect) {
|
|
266
222
|
logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
|
|
267
|
-
this.blockReconnect = true;
|
|
223
|
+
this.connectionsMap[connectionPurpose].blockReconnect = true;
|
|
268
224
|
}
|
|
269
225
|
else {
|
|
270
226
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
271
227
|
}
|
|
272
228
|
});
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.
|
|
276
|
-
this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
229
|
+
newConnection.once('connect', async () => {
|
|
230
|
+
this.connectionsMap[connectionPurpose].creatingConnection = false;
|
|
231
|
+
this.em.emit(connectionCreatedEventName, newConnection);
|
|
277
232
|
isResolved = true;
|
|
278
|
-
resolve(
|
|
233
|
+
resolve(newConnection);
|
|
279
234
|
});
|
|
280
235
|
});
|
|
281
236
|
}
|
|
282
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
237
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connectionPurpose = consts_1.ConnectionPurpose.Consume, }) {
|
|
283
238
|
let connection;
|
|
284
239
|
try {
|
|
285
|
-
connection = await this.getConnection();
|
|
240
|
+
connection = await this.getConnection(connectionPurpose);
|
|
286
241
|
}
|
|
287
242
|
catch (e) {
|
|
288
243
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
289
244
|
throw e;
|
|
290
245
|
}
|
|
246
|
+
if (!connection) {
|
|
247
|
+
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
248
|
+
}
|
|
291
249
|
const channel = connection.createChannel({ ...options });
|
|
292
250
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
293
251
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
@@ -303,18 +261,22 @@ class RabbitMq {
|
|
|
303
261
|
throw err;
|
|
304
262
|
}
|
|
305
263
|
}
|
|
306
|
-
async assertChannel({ force = false
|
|
264
|
+
async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume }) {
|
|
265
|
+
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
|
|
307
266
|
if (!this.publishChannelSetupPromise) {
|
|
308
267
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
309
|
-
if (this.
|
|
310
|
-
return resolve(this.
|
|
268
|
+
if (this.publishChannel && !force) {
|
|
269
|
+
return resolve(this.publishChannel);
|
|
311
270
|
}
|
|
312
271
|
try {
|
|
313
|
-
const channel = await this.getNewChannel({});
|
|
272
|
+
const channel = await this.getNewChannel({ connectionPurpose });
|
|
273
|
+
debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
|
|
314
274
|
channel.on('error', (err) => {
|
|
315
275
|
logger_1.default.error('rabbit: channel error', { err });
|
|
316
276
|
});
|
|
317
|
-
|
|
277
|
+
if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
|
|
278
|
+
this.publishChannel = channel;
|
|
279
|
+
}
|
|
318
280
|
resolve(channel);
|
|
319
281
|
}
|
|
320
282
|
catch (e) {
|
|
@@ -324,8 +286,8 @@ class RabbitMq {
|
|
|
324
286
|
}
|
|
325
287
|
return this.publishChannelSetupPromise;
|
|
326
288
|
}
|
|
327
|
-
async assertExchange(exchangeName, options) {
|
|
328
|
-
const channel = await this.assertChannel();
|
|
289
|
+
async assertExchange(exchangeName, options = { connectionPurpose: consts_1.ConnectionPurpose.Consume }) {
|
|
290
|
+
const channel = await this.assertChannel({ connectionPurpose: options.connectionPurpose });
|
|
329
291
|
if (this.exchanges[exchangeName]) {
|
|
330
292
|
delete this.assertExchangePromises[exchangeName];
|
|
331
293
|
return this.exchanges[exchangeName];
|
|
@@ -337,47 +299,46 @@ class RabbitMq {
|
|
|
337
299
|
this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];
|
|
338
300
|
return this.exchanges[exchangeName];
|
|
339
301
|
}
|
|
340
|
-
|
|
341
|
-
async getQueueLength(queue) {
|
|
302
|
+
async getQueueLength(queue, connectionPurpose = consts_1.ConnectionPurpose.Consume) {
|
|
342
303
|
RabbitMq.validateName('queue', queue);
|
|
343
|
-
const {
|
|
344
|
-
|
|
345
|
-
|
|
304
|
+
const { connection } = this.connectionsMap[connectionPurpose];
|
|
305
|
+
const { publishChannel } = this;
|
|
306
|
+
if (!publishChannel) {
|
|
307
|
+
throw new Error('channel is not defined');
|
|
346
308
|
}
|
|
347
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
348
|
-
return
|
|
309
|
+
debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
|
|
310
|
+
return publishChannel?.checkQueue(queue);
|
|
349
311
|
}
|
|
350
|
-
async deleteQueue(queue) {
|
|
312
|
+
async deleteQueue(queue, connectionPurpose) {
|
|
351
313
|
RabbitMq.validateName('queue', queue);
|
|
352
|
-
const channel = await this.assertChannel();
|
|
314
|
+
const channel = await this.assertChannel({ connectionPurpose });
|
|
353
315
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
354
316
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
355
317
|
debug('queue deleted', deleteQueueRes);
|
|
356
318
|
return deleteQueueRes;
|
|
357
319
|
}
|
|
358
|
-
// TODO: [QUORUM-PHASE-2] Change the implementation to the new one
|
|
359
320
|
async bindQueue(queue, exchange) {
|
|
360
|
-
const channel = await this.
|
|
321
|
+
const channel = await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
361
322
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
362
323
|
return channel.bindQueue(queue, exchange, '');
|
|
363
324
|
}
|
|
364
325
|
async setupQueue(queueName, options) {
|
|
365
326
|
let queue;
|
|
327
|
+
const connectionPurpose = consts_1.ConnectionPurpose.Publish;
|
|
328
|
+
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
366
329
|
const localeOptions = {
|
|
367
330
|
...options,
|
|
368
331
|
durable: true,
|
|
369
332
|
arguments: {
|
|
370
333
|
...options?.arguments,
|
|
371
334
|
'x-consumer-timeout': 1000 * 60 * 60 * 24,
|
|
372
|
-
'x-queue-type': 'quorum',
|
|
335
|
+
'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',
|
|
373
336
|
},
|
|
374
337
|
};
|
|
375
338
|
try {
|
|
376
|
-
const channel = await this.assertChannel();
|
|
339
|
+
const channel = await this.assertChannel({ connectionPurpose });
|
|
377
340
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
378
|
-
await channel.addSetup(
|
|
379
|
-
await setupChannel.assertQueue(queueName, localeOptions);
|
|
380
|
-
});
|
|
341
|
+
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
381
342
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
382
343
|
queue = await channel.assertQueue(queueName, localeOptions);
|
|
383
344
|
}
|
|
@@ -385,8 +346,8 @@ class RabbitMq {
|
|
|
385
346
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
386
347
|
if (!this.options?.dontRetryAssert) {
|
|
387
348
|
debug('retrying assertQueue', { queueName });
|
|
388
|
-
const channel = await this.assertChannel({ force: true });
|
|
389
|
-
await this.deleteQueue(queueName);
|
|
349
|
+
const channel = await this.assertChannel({ force: true, connectionPurpose });
|
|
350
|
+
await this.deleteQueue(queueName, connectionPurpose);
|
|
390
351
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
391
352
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
392
353
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -399,7 +360,6 @@ class RabbitMq {
|
|
|
399
360
|
this.queues[queueName] = queue;
|
|
400
361
|
return queue;
|
|
401
362
|
}
|
|
402
|
-
// TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues
|
|
403
363
|
static shouldUseQuorum(queueName) {
|
|
404
364
|
const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;
|
|
405
365
|
if (envQuorumQueuesWhitelist === '*') {
|
|
@@ -412,6 +372,7 @@ class RabbitMq {
|
|
|
412
372
|
return false;
|
|
413
373
|
}
|
|
414
374
|
async assertQueue(queueName, options) {
|
|
375
|
+
debug('rabbit: start assert queue', { queueName });
|
|
415
376
|
RabbitMq.validateName('queue', queueName);
|
|
416
377
|
if (this.queues[queueName]) {
|
|
417
378
|
delete this.queueSetupPromises[queueName];
|
|
@@ -421,6 +382,7 @@ class RabbitMq {
|
|
|
421
382
|
return this.queueSetupPromises[queueName];
|
|
422
383
|
}
|
|
423
384
|
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
385
|
+
debug('rabbit: done assert queue', { queueName });
|
|
424
386
|
return this.queueSetupPromises[queueName];
|
|
425
387
|
}
|
|
426
388
|
saveConsumer(queue, callback, options) {
|
|
@@ -434,23 +396,9 @@ class RabbitMq {
|
|
|
434
396
|
});
|
|
435
397
|
}
|
|
436
398
|
}
|
|
437
|
-
// Used by the microservices to consume messages from the queue
|
|
438
399
|
async consume(queue, callback, options) {
|
|
439
|
-
// TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld
|
|
440
|
-
if (options?.isQuorumQueue !== false) {
|
|
441
|
-
await this.assertVHost();
|
|
442
|
-
await this.consumeNew(queue, callback, options);
|
|
443
|
-
}
|
|
444
|
-
await this.consumeOld(queue, callback, options);
|
|
445
|
-
}
|
|
446
|
-
// TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore
|
|
447
|
-
async consumeNew(queue, callback, options) {
|
|
448
400
|
await this.consumeFromRabbit(queue, callback, options);
|
|
449
401
|
}
|
|
450
|
-
// TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore
|
|
451
|
-
async consumeOld(queue, callback, options) {
|
|
452
|
-
await this.consumeFromRabbitOld(queue, callback, options);
|
|
453
|
-
}
|
|
454
402
|
async lockRedisIfNeeded(msg, options) {
|
|
455
403
|
const { properties: { headers } } = msg;
|
|
456
404
|
const timestamp = headers?.creationTimestamp;
|
|
@@ -473,13 +421,12 @@ class RabbitMq {
|
|
|
473
421
|
const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace, } = optionsWithDefaults;
|
|
474
422
|
if (useConsumeWithLock) {
|
|
475
423
|
if (!this.redisLock) {
|
|
476
|
-
throw new
|
|
424
|
+
throw new Error('Usage of consumeWithLock requires RedisInstance');
|
|
477
425
|
}
|
|
478
426
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
479
427
|
}
|
|
480
|
-
const channel = await this.getNewChannel({});
|
|
428
|
+
const channel = await this.getNewChannel({ connectionPurpose: consts_1.ConnectionPurpose.Consume });
|
|
481
429
|
return channel.addSetup(async (confirmChannel) => {
|
|
482
|
-
throw new Error('Dummy assertQueue error');
|
|
483
430
|
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
484
431
|
await confirmChannel.prefetch(limit, false);
|
|
485
432
|
const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
|
|
@@ -556,57 +503,36 @@ class RabbitMq {
|
|
|
556
503
|
}
|
|
557
504
|
});
|
|
558
505
|
}
|
|
559
|
-
// Used by the microservices to consume messages from the exchange
|
|
560
506
|
async consumeFromExchange(queue, exchange, callback, options) {
|
|
561
507
|
const optionsWithDefaults = { ...consts_1.DEFAULT_OPTIONS, ...options };
|
|
562
508
|
RabbitMq.validateName('exchange', exchange);
|
|
563
509
|
RabbitMq.validateName('queue', queue);
|
|
564
510
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
await this.saveConsumer(queue, callback, options);
|
|
569
|
-
const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
570
|
-
await channel.addSetup(async (c) => {
|
|
571
|
-
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
572
|
-
await c.assertQueue(queue);
|
|
573
|
-
this.exchanges[exchange] = assertExchange;
|
|
574
|
-
await c.prefetch(limit, false);
|
|
575
|
-
return Promise.all([
|
|
576
|
-
c.bindQueue(queue, exchange, ''),
|
|
577
|
-
this.consumeNew(queue, callback, options),
|
|
578
|
-
]);
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
// TODO: [QUORUM-PHASE-3] Delete the old implementation
|
|
582
|
-
await this.saveConsumerOld(queue, callback, options);
|
|
583
|
-
const channelOld = await this.getNewChannelOld({ name: `consume-exchange-${exchange}-queue-${queue}-old` });
|
|
584
|
-
await channelOld.addSetup(async (c) => {
|
|
511
|
+
await this.saveConsumer(queue, callback, options);
|
|
512
|
+
const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
513
|
+
return channel.addSetup(async (c) => {
|
|
585
514
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
586
515
|
await c.assertQueue(queue);
|
|
587
|
-
this.
|
|
516
|
+
this.exchanges[exchange] = assertExchange;
|
|
588
517
|
await c.prefetch(limit, false);
|
|
589
518
|
return Promise.all([
|
|
590
519
|
c.bindQueue(queue, exchange, ''),
|
|
591
|
-
this.
|
|
520
|
+
this.consume(queue, callback, options),
|
|
592
521
|
]);
|
|
593
522
|
});
|
|
594
523
|
}
|
|
595
|
-
// Used by the microservices to publish messages to the exchange
|
|
596
|
-
// TODO: [QUORUM-PHASE-2] Change the implementation to the new one
|
|
597
524
|
async publish(exchange, content, customHeaders) {
|
|
525
|
+
debug('rabbit: start publish msg');
|
|
598
526
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
599
527
|
RabbitMq.validateName('exchange', exchange);
|
|
600
|
-
const channel = await this.
|
|
601
|
-
await this.
|
|
528
|
+
const channel = await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
529
|
+
await this.assertExchange(exchange, { connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
602
530
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
603
531
|
});
|
|
604
532
|
}
|
|
605
|
-
// Used by the microservices to send messages to the queue
|
|
606
|
-
// TODO: [QUORUM-PHASE-2] Change the implementation to the new one
|
|
607
533
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
608
534
|
try {
|
|
609
|
-
await this.
|
|
535
|
+
await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
610
536
|
}
|
|
611
537
|
catch (e) {
|
|
612
538
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -614,55 +540,56 @@ class RabbitMq {
|
|
|
614
540
|
}
|
|
615
541
|
try {
|
|
616
542
|
RabbitMq.validateName('queue', queue);
|
|
617
|
-
await this.
|
|
543
|
+
await this.assertQueue(queue, options);
|
|
618
544
|
}
|
|
619
545
|
catch (e) {
|
|
620
546
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
621
547
|
throw e;
|
|
622
548
|
}
|
|
623
549
|
try {
|
|
624
|
-
const res = await this.
|
|
550
|
+
const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
625
551
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
626
552
|
return res;
|
|
627
553
|
}
|
|
628
554
|
catch (e) {
|
|
629
|
-
|
|
630
|
-
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
555
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}`, { e });
|
|
631
556
|
throw e;
|
|
632
557
|
}
|
|
633
558
|
}
|
|
634
|
-
// TODO: [QUORUM-PHASE-2] After changing the publish from old to new change from the old to the new implementation
|
|
635
559
|
async isConnected() {
|
|
636
|
-
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
channel.
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
560
|
+
debug('rabbit: start is connected');
|
|
561
|
+
const isEachConnectionConnected = await Promise.all(Object.keys(this.connectionsMap).map(async (connectionPurpose) => {
|
|
562
|
+
const connection = await this.getConnection(connectionPurpose);
|
|
563
|
+
const isConnected = connection?.isConnected();
|
|
564
|
+
if (!isConnected) {
|
|
565
|
+
logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
|
|
566
|
+
return false;
|
|
567
|
+
}
|
|
568
|
+
if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
|
|
569
|
+
const channel = await this.assertChannel({ connectionPurpose: connectionPurpose });
|
|
570
|
+
try {
|
|
571
|
+
await Promise.all([
|
|
572
|
+
channel.waitForConnect(),
|
|
573
|
+
...this.consumers.map((c) => channel.checkQueue(c.queue)),
|
|
574
|
+
]);
|
|
575
|
+
}
|
|
576
|
+
catch (e) {
|
|
577
|
+
logger_1.default.error('rabbit: isConnected - false');
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
logger_1.default.info('rabbit: isConnected - true', { connectionPurpose });
|
|
582
|
+
return true;
|
|
583
|
+
}));
|
|
584
|
+
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
|
655
585
|
}
|
|
656
586
|
async gracefulShutdown(signal) {
|
|
657
|
-
|
|
658
|
-
const tagsNumber = this.consumersTags.length + this.oldConsumersTags.length;
|
|
587
|
+
const tagsNumber = this.consumersTags.length;
|
|
659
588
|
logger_1.default.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);
|
|
660
589
|
const cancelTagPromises = this.consumersTags.map(([channel, tag]) => channel.cancel(tag));
|
|
661
|
-
const cancelTagPromisesOld = this.oldConsumersTags.map(([channel, tag]) => channel.cancel(tag));
|
|
662
590
|
// Clean the array to avoid race
|
|
663
591
|
this.consumersTags = [];
|
|
664
|
-
|
|
665
|
-
const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);
|
|
592
|
+
const results = await Promise.allSettled(cancelTagPromises);
|
|
666
593
|
const rejected = results.filter((p) => p.status === 'rejected');
|
|
667
594
|
if (rejected.length > 0) {
|
|
668
595
|
logger_1.default.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected}`);
|
|
@@ -671,300 +598,6 @@ class RabbitMq {
|
|
|
671
598
|
logger_1.default.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');
|
|
672
599
|
}
|
|
673
600
|
}
|
|
674
|
-
async consumeFromRabbitOld(queue, callback, options) {
|
|
675
|
-
const optionsWithDefaults = { ...consts_1.DEFAULT_OPTIONS, ...options };
|
|
676
|
-
RabbitMq.validateName('queue', queue);
|
|
677
|
-
this.saveConsumerOld(queue, callback, options);
|
|
678
|
-
const uniqueId = (0, node_crypto_1.randomUUID)();
|
|
679
|
-
const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace, } = optionsWithDefaults;
|
|
680
|
-
if (useConsumeWithLock) {
|
|
681
|
-
if (!this.redisLock) {
|
|
682
|
-
throw new rabbitError_1.default('Usage of consumeWithLock requires RedisInstance');
|
|
683
|
-
}
|
|
684
|
-
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
685
|
-
}
|
|
686
|
-
const channel = await this.getNewChannelOld({});
|
|
687
|
-
return channel.addSetup(async (confirmChannel) => {
|
|
688
|
-
const q = await this.assertQueueOld(queue, optionsWithDefaults);
|
|
689
|
-
await confirmChannel.prefetch(limit, false);
|
|
690
|
-
const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
|
|
691
|
-
if (!msg) {
|
|
692
|
-
return null;
|
|
693
|
-
}
|
|
694
|
-
const traceId = msg.properties.headers[consts_1.TRACING_HEADER];
|
|
695
|
-
const userId = msg.properties.headers[consts_1.USER_TRACING_HEADER];
|
|
696
|
-
const automationId = msg.properties.headers[consts_1.AUTOMATION_ID_HEADER];
|
|
697
|
-
const parsedMessage = RabbitMq.parseMsg(msg);
|
|
698
|
-
const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
|
|
699
|
-
const trace = (0, zehut_1.newTrace)(zehut_1.traceTypes.RABBIT);
|
|
700
|
-
// setting also outbreak trace as part of legacy code
|
|
701
|
-
const outbreakTrace = zehut_1.outbreak.newTrace(zehut_1.traceTypes.RABBIT);
|
|
702
|
-
// enableRabbitTrace is a flag to protect from different flows that doesn't work with permission
|
|
703
|
-
// and we don't want to fail the flow because of it
|
|
704
|
-
if (userId && enableRabbitTrace) {
|
|
705
|
-
try {
|
|
706
|
-
await Promise.all([
|
|
707
|
-
(0, zehut_1.createOrSetRabbitTrace)(trace, userId),
|
|
708
|
-
(0, zehut_1.createOrSetRabbitTrace)(outbreakTrace, userId),
|
|
709
|
-
]);
|
|
710
|
-
}
|
|
711
|
-
catch (e) {
|
|
712
|
-
logger_1.default.error('rabbit: failed to setRabbitTrace', { userId, e });
|
|
713
|
-
return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
if (traceId) {
|
|
717
|
-
trace?.context?.set(consts_1.TRACING_HEADER, traceId);
|
|
718
|
-
outbreakTrace?.context.set(consts_1.TRACING_HEADER, traceId);
|
|
719
|
-
}
|
|
720
|
-
if (auditContext) {
|
|
721
|
-
await auditContext(queue, {
|
|
722
|
-
userId,
|
|
723
|
-
automationId,
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
|
-
const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
|
|
727
|
-
if (!shouldConsume) {
|
|
728
|
-
await this.unlockRedisIfNeeded(releaseLock);
|
|
729
|
-
return this.ack(confirmChannel, msg)(msg);
|
|
730
|
-
}
|
|
731
|
-
let messageAcked = false;
|
|
732
|
-
// setting the localAck function to be used in the callback
|
|
733
|
-
const localAck = async () => {
|
|
734
|
-
if (messageAcked) {
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
messageAcked = true;
|
|
738
|
-
return this.ack(confirmChannel, msg, true, releaseLock)(msg);
|
|
739
|
-
};
|
|
740
|
-
const localNack = async (_, nackOptions = {}) => {
|
|
741
|
-
if (messageAcked) {
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });
|
|
745
|
-
messageAcked = true;
|
|
746
|
-
return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);
|
|
747
|
-
};
|
|
748
|
-
try {
|
|
749
|
-
await callback(parsedMessage, localAck, localNack);
|
|
750
|
-
}
|
|
751
|
-
catch (e) {
|
|
752
|
-
await localNack(msg);
|
|
753
|
-
}
|
|
754
|
-
}, types_1.CONSUMER_DEFAULT_OPTIONS);
|
|
755
|
-
if (!consumerTag) {
|
|
756
|
-
logger_1.default.error(`rabbit: failed to consume from queue ${queue}`);
|
|
757
|
-
}
|
|
758
|
-
else {
|
|
759
|
-
logger_1.default.info(`rabbit: adding tag ${consumerTag} to the array.`);
|
|
760
|
-
this.oldConsumersTags.push([confirmChannel, consumerTag]);
|
|
761
|
-
}
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
// TODO: [QUORUM-PHASE-3] Delete all the function under this line (getNewChannelOld, getConnectionOld, assertQueueOld, setupQueueOld, saveConsumerOld)
|
|
765
|
-
async getNewChannelOld({ name = (0, utils_1.rand)().toString(), onClose = null, options = {} } = {}) {
|
|
766
|
-
let connection;
|
|
767
|
-
try {
|
|
768
|
-
connection = await this.getConnectionOld();
|
|
769
|
-
}
|
|
770
|
-
catch (e) {
|
|
771
|
-
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
772
|
-
throw e;
|
|
773
|
-
}
|
|
774
|
-
const channel = connection.createChannel({ ...options });
|
|
775
|
-
(0, events_1.once)(channel, 'close').then((args) => {
|
|
776
|
-
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
777
|
-
onClose?.(args);
|
|
778
|
-
});
|
|
779
|
-
try {
|
|
780
|
-
await (0, events_1.once)(channel, 'connect');
|
|
781
|
-
debug(`rabbit: channel ${name} CONNECTED`);
|
|
782
|
-
return channel;
|
|
783
|
-
}
|
|
784
|
-
catch (err) {
|
|
785
|
-
logger_1.default.error(`rabbit: channel error ${name} error`, { err });
|
|
786
|
-
throw err;
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
async getConnectionOld() {
|
|
790
|
-
return new Promise(async (resolve, reject) => {
|
|
791
|
-
if (this.oldBlockReconnect) {
|
|
792
|
-
debug('rabbit: block reconnect');
|
|
793
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
794
|
-
// @ts-ignore
|
|
795
|
-
return resolve();
|
|
796
|
-
}
|
|
797
|
-
if (this.oldConnection !== null) {
|
|
798
|
-
if (this.options?.disableReconnect || this.oldConnection?.isConnected()) {
|
|
799
|
-
debug('rabbit: connection - is connected');
|
|
800
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
801
|
-
// @ts-ignore
|
|
802
|
-
return resolve(this.oldConnection);
|
|
803
|
-
}
|
|
804
|
-
debug('rabbit: connection - reconnecting');
|
|
805
|
-
}
|
|
806
|
-
if (this.oldCreatingConnection) {
|
|
807
|
-
debug('rabbit: creating connection emi');
|
|
808
|
-
this.oldEm.once(consts_1.CONNECTION_CREATED_CONST, resolve);
|
|
809
|
-
this.oldEm.once(consts_1.CONNECTION_FAILED_CONST, reject);
|
|
810
|
-
return;
|
|
811
|
-
}
|
|
812
|
-
this.oldCreatingConnection = true;
|
|
813
|
-
let isResolved = false;
|
|
814
|
-
// It is import to use it as a function and not as a variable
|
|
815
|
-
// because of k8s changes the env variables
|
|
816
|
-
// and we want to use the new values
|
|
817
|
-
const findServers = () => {
|
|
818
|
-
const userName = process.env.RABBITMQ_USERNAME || 'guest';
|
|
819
|
-
const password = process.env.RABBITMQ_PASSWORD || 'guest';
|
|
820
|
-
const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';
|
|
821
|
-
debug('rabbit: creating connection', { host, userName, HEARTBEAT });
|
|
822
|
-
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
823
|
-
};
|
|
824
|
-
const defaultUrls = findServers();
|
|
825
|
-
const connection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
826
|
-
findServers,
|
|
827
|
-
});
|
|
828
|
-
this.oldConnection = connection;
|
|
829
|
-
this.oldConnection.on('error', (err) => {
|
|
830
|
-
logger_1.default.error('rabbit: connection error', { err });
|
|
831
|
-
if (!isResolved) {
|
|
832
|
-
isResolved = true;
|
|
833
|
-
reject(err);
|
|
834
|
-
this.oldEm.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
this.oldConnection.on('connectFailed', (err) => {
|
|
838
|
-
this.oldConsumersTags = [];
|
|
839
|
-
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
840
|
-
if (!isResolved) {
|
|
841
|
-
isResolved = true;
|
|
842
|
-
reject(err);
|
|
843
|
-
this.oldEm.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
this.oldConnection.on('disconnect', ({ err }) => {
|
|
847
|
-
this.oldConsumersTags = [];
|
|
848
|
-
debug('rabbit: connection closed');
|
|
849
|
-
if (this.options?.disableReconnect) {
|
|
850
|
-
logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
|
|
851
|
-
this.oldBlockReconnect = true;
|
|
852
|
-
}
|
|
853
|
-
else {
|
|
854
|
-
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
this.oldConnection.once('connect', async () => {
|
|
858
|
-
debug('rabbit: connection established');
|
|
859
|
-
this.oldCreatingConnection = false;
|
|
860
|
-
this.oldEm.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
861
|
-
isResolved = true;
|
|
862
|
-
resolve(connection);
|
|
863
|
-
});
|
|
864
|
-
});
|
|
865
|
-
}
|
|
866
|
-
saveConsumerOld(queue, callback, options) {
|
|
867
|
-
const isConsumerExist = this.oldConsumers.some((consumer) => consumer.queue === queue);
|
|
868
|
-
if (!isConsumerExist) {
|
|
869
|
-
logger_1.default.info(`rabbit: consumer: ${queue} saved in consumer array`);
|
|
870
|
-
this.oldConsumers.push({
|
|
871
|
-
queue,
|
|
872
|
-
callback,
|
|
873
|
-
options,
|
|
874
|
-
});
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
async assertQueueOld(queueName, options) {
|
|
878
|
-
RabbitMq.validateName('queue', queueName);
|
|
879
|
-
if (this.oldQueues[queueName]) {
|
|
880
|
-
delete this.oldQueueSetupPromises[queueName];
|
|
881
|
-
return this.oldQueues[queueName];
|
|
882
|
-
}
|
|
883
|
-
if (this.oldQueueSetupPromises[queueName]) {
|
|
884
|
-
return this.oldQueueSetupPromises[queueName];
|
|
885
|
-
}
|
|
886
|
-
this.oldQueueSetupPromises[queueName] = this.setupQueueOld(queueName, options);
|
|
887
|
-
return this.oldQueueSetupPromises[queueName];
|
|
888
|
-
}
|
|
889
|
-
async setupQueueOld(queueName, options) {
|
|
890
|
-
let queue;
|
|
891
|
-
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
892
|
-
const localeOptions = {
|
|
893
|
-
...options,
|
|
894
|
-
durable: true,
|
|
895
|
-
arguments: {
|
|
896
|
-
...options?.arguments,
|
|
897
|
-
'x-consumer-timeout': 1000 * 60 * 60 * 24,
|
|
898
|
-
'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',
|
|
899
|
-
},
|
|
900
|
-
};
|
|
901
|
-
try {
|
|
902
|
-
const channel = await this.assertChannelOld();
|
|
903
|
-
debug('assertQueue->channel.addSetup', { queueName });
|
|
904
|
-
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
905
|
-
debug('assertQueue->channel.assertQueue', { queueName });
|
|
906
|
-
queue = await channel.assertQueue(queueName, localeOptions);
|
|
907
|
-
}
|
|
908
|
-
catch (e) {
|
|
909
|
-
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
910
|
-
if (!this.options?.dontRetryAssert) {
|
|
911
|
-
debug('retrying assertQueue', { queueName });
|
|
912
|
-
const channel = await this.assertChannelOld({ force: true });
|
|
913
|
-
await this.deleteQueueOld(queueName);
|
|
914
|
-
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
915
|
-
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
916
|
-
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
917
|
-
queue = await channel.assertQueue(queueName, localeOptions);
|
|
918
|
-
}
|
|
919
|
-
else {
|
|
920
|
-
throw e;
|
|
921
|
-
}
|
|
922
|
-
}
|
|
923
|
-
this.oldQueues[queueName] = queue;
|
|
924
|
-
return queue;
|
|
925
|
-
}
|
|
926
|
-
async assertChannelOld({ force = false } = {}) {
|
|
927
|
-
if (!this.oldPublishChannelSetupPromise) {
|
|
928
|
-
this.oldPublishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
929
|
-
if (this.oldChannel && !force) {
|
|
930
|
-
return resolve(this.oldChannel);
|
|
931
|
-
}
|
|
932
|
-
try {
|
|
933
|
-
const channel = await this.getNewChannelOld({});
|
|
934
|
-
channel.on('error', (err) => {
|
|
935
|
-
logger_1.default.error('rabbit: channel error', { err });
|
|
936
|
-
});
|
|
937
|
-
this.oldChannel = channel;
|
|
938
|
-
resolve(channel);
|
|
939
|
-
}
|
|
940
|
-
catch (e) {
|
|
941
|
-
reject(e);
|
|
942
|
-
}
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
return this.oldPublishChannelSetupPromise;
|
|
946
|
-
}
|
|
947
|
-
async deleteQueueOld(queue) {
|
|
948
|
-
RabbitMq.validateName('queue', queue);
|
|
949
|
-
const channel = await this.assertChannelOld();
|
|
950
|
-
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
951
|
-
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
952
|
-
debug('queue deleted', deleteQueueRes);
|
|
953
|
-
return deleteQueueRes;
|
|
954
|
-
}
|
|
955
|
-
async assertExchangeOld(exchangeName, options) {
|
|
956
|
-
const channel = await this.assertChannelOld();
|
|
957
|
-
if (this.oldExchanges[exchangeName]) {
|
|
958
|
-
delete this.oldAssertExchangePromises[exchangeName];
|
|
959
|
-
return this.oldExchanges[exchangeName];
|
|
960
|
-
}
|
|
961
|
-
if (this.oldAssertExchangePromises[exchangeName]) {
|
|
962
|
-
return this.oldAssertExchangePromises[exchangeName];
|
|
963
|
-
}
|
|
964
|
-
this.oldAssertExchangePromises[exchangeName] = (0, utils_1.assertExchangeFanout)(channel, exchangeName);
|
|
965
|
-
this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];
|
|
966
|
-
return this.oldExchanges[exchangeName];
|
|
967
|
-
}
|
|
968
601
|
}
|
|
969
602
|
exports.default = RabbitMq;
|
|
970
603
|
var celery_1 = require("./lib/celery");
|