@autofleet/rabbit 3.2.24-beta.4 → 3.2.24-beta.6
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/dist/index.d.ts +10 -15
- package/dist/index.js +69 -97
- package/dist/lib/consts.d.ts +2 -4
- package/dist/lib/consts.js +3 -6
- package/dist/lib/types.d.ts +0 -7
- package/package.json +3 -2
- package/src/index.ts +88 -126
- package/src/lib/consts.ts +2 -5
- package/src/lib/types.ts +0 -8
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,7 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from 'amqp-connection-manager';
|
|
4
4
|
import { ConfirmChannel, ConsumeMessage, Options, Replies } from 'amqplib';
|
|
5
5
|
import { RedisConfig } from './lib/redis';
|
|
6
|
-
import {
|
|
7
|
-
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData } from './lib/types';
|
|
6
|
+
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary } from './lib/types';
|
|
8
7
|
export interface IAfRabbitMq {
|
|
9
8
|
ack: any;
|
|
10
9
|
nack: any;
|
|
@@ -38,12 +37,10 @@ type newChannelOpts = {
|
|
|
38
37
|
name?: string;
|
|
39
38
|
onClose?: null | ((args: any | null) => void);
|
|
40
39
|
options?: CreateChannelOpts | undefined;
|
|
41
|
-
connectionPurpose?: ConnectionPurpose;
|
|
42
40
|
};
|
|
43
41
|
type assertChannelOpts = {
|
|
44
42
|
channelName?: string;
|
|
45
43
|
force?: boolean;
|
|
46
|
-
connectionPurpose?: ConnectionPurpose;
|
|
47
44
|
};
|
|
48
45
|
declare class RabbitMq implements IAfRabbitMq {
|
|
49
46
|
static parseMsg(msg: any): any;
|
|
@@ -63,11 +60,9 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
63
60
|
channel: ChannelWrapper | null;
|
|
64
61
|
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
65
62
|
blockReconnect: boolean | null | undefined;
|
|
66
|
-
|
|
67
|
-
[ConnectionPurpose.Consume]: ConnectionData;
|
|
68
|
-
[ConnectionPurpose.Publish]: ConnectionData;
|
|
69
|
-
};
|
|
63
|
+
connection: AmqpConnectionManager | null | undefined;
|
|
70
64
|
em: EventEmitter;
|
|
65
|
+
creatingConnection: boolean;
|
|
71
66
|
exchanges: ExchangesCache;
|
|
72
67
|
queues: QueuesCache;
|
|
73
68
|
queueSetupPromises: QueueSetupPromisesDictionary;
|
|
@@ -82,16 +77,16 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
82
77
|
private shouldConsumeMessageByTimestamp;
|
|
83
78
|
ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
|
|
84
79
|
nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
|
|
85
|
-
getConnection(
|
|
86
|
-
getNewChannel({ name, onClose, options
|
|
87
|
-
assertChannel({ force
|
|
80
|
+
getConnection(): Promise<AmqpConnectionManager>;
|
|
81
|
+
getNewChannel({ name, onClose, options }?: newChannelOpts): Promise<ChannelWrapper>;
|
|
82
|
+
assertChannel({ force }?: assertChannelOpts): Promise<ChannelWrapper>;
|
|
88
83
|
assertExchange(exchangeName: string, options?: any): Promise<any>;
|
|
89
|
-
getQueueLength(queue: string
|
|
84
|
+
getQueueLength(queue: string): Promise<Replies.AssertQueue>;
|
|
90
85
|
private deleteQueue;
|
|
91
|
-
bindQueue(queue: string, exchange: string
|
|
92
|
-
setupQueue(queueName: string,
|
|
86
|
+
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
87
|
+
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
93
88
|
static shouldUseQuorum(queueName: string): boolean;
|
|
94
|
-
assertQueue(queueName: string,
|
|
89
|
+
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
|
|
95
90
|
private saveConsumer;
|
|
96
91
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
97
92
|
private lockRedisIfNeeded;
|
package/dist/index.js
CHANGED
|
@@ -119,20 +119,8 @@ class RabbitMq {
|
|
|
119
119
|
this.em = new events_1.EventEmitter();
|
|
120
120
|
this.channel = null;
|
|
121
121
|
this.publishChannelSetupPromise = null;
|
|
122
|
-
this.
|
|
123
|
-
|
|
124
|
-
connection: null,
|
|
125
|
-
creatingConnection: false,
|
|
126
|
-
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
127
|
-
connectionFailedEventName: 'consumeConnectionFailed',
|
|
128
|
-
},
|
|
129
|
-
[consts_1.ConnectionPurpose.Publish]: {
|
|
130
|
-
connection: null,
|
|
131
|
-
creatingConnection: false,
|
|
132
|
-
connectionCreatedEventName: 'publishConnectionCreated',
|
|
133
|
-
connectionFailedEventName: 'publishConnectionFailed',
|
|
134
|
-
},
|
|
135
|
-
};
|
|
122
|
+
this.connection = null;
|
|
123
|
+
this.creatingConnection = false;
|
|
136
124
|
this.exchanges = {};
|
|
137
125
|
this.queues = {};
|
|
138
126
|
this.queueSetupPromises = {};
|
|
@@ -154,31 +142,30 @@ class RabbitMq {
|
|
|
154
142
|
});
|
|
155
143
|
}
|
|
156
144
|
}
|
|
157
|
-
async getConnection(
|
|
145
|
+
async getConnection() {
|
|
158
146
|
return new Promise(async (resolve, reject) => {
|
|
159
|
-
const { connection, creatingConnection, connectionCreatedEventName, connectionFailedEventName, } = this.connectionsMap[connectionPurpose];
|
|
160
147
|
if (this.blockReconnect) {
|
|
161
148
|
debug('rabbit: block reconnect');
|
|
162
149
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
163
150
|
// @ts-ignore
|
|
164
151
|
return resolve();
|
|
165
152
|
}
|
|
166
|
-
if (connection !== null) {
|
|
167
|
-
if (this.options?.disableReconnect || connection?.isConnected()) {
|
|
153
|
+
if (this.connection !== null) {
|
|
154
|
+
if (this.options?.disableReconnect || this.connection?.isConnected()) {
|
|
168
155
|
debug('rabbit: connection - is connected');
|
|
169
156
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
170
157
|
// @ts-ignore
|
|
171
|
-
return resolve(connection);
|
|
158
|
+
return resolve(this.connection);
|
|
172
159
|
}
|
|
173
160
|
debug('rabbit: connection - reconnecting');
|
|
174
161
|
}
|
|
175
|
-
if (creatingConnection) {
|
|
162
|
+
if (this.creatingConnection) {
|
|
176
163
|
debug('rabbit: creating connection emi');
|
|
177
|
-
this.em.once(
|
|
178
|
-
this.em.once(
|
|
164
|
+
this.em.once(consts_1.CONNECTION_CREATED_CONST, resolve);
|
|
165
|
+
this.em.once(consts_1.CONNECTION_FAILED_CONST, reject);
|
|
179
166
|
return;
|
|
180
167
|
}
|
|
181
|
-
this.
|
|
168
|
+
this.creatingConnection = true;
|
|
182
169
|
let isResolved = false;
|
|
183
170
|
// It is import to use it as a function and not as a variable
|
|
184
171
|
// because of k8s changes the env variables
|
|
@@ -191,29 +178,29 @@ class RabbitMq {
|
|
|
191
178
|
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
192
179
|
};
|
|
193
180
|
const defaultUrls = findServers();
|
|
194
|
-
const
|
|
181
|
+
const connection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
195
182
|
findServers,
|
|
196
183
|
});
|
|
197
|
-
this.
|
|
198
|
-
|
|
199
|
-
newConnection.on('error', (err) => {
|
|
184
|
+
this.connection = connection;
|
|
185
|
+
this.connection.on('error', (err) => {
|
|
200
186
|
logger_1.default.error('rabbit: connection error', { err });
|
|
201
187
|
if (!isResolved) {
|
|
202
188
|
isResolved = true;
|
|
203
189
|
reject(err);
|
|
204
|
-
this.em.emit(
|
|
190
|
+
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
205
191
|
}
|
|
206
192
|
});
|
|
207
|
-
|
|
193
|
+
this.connection.on('connectFailed', (err) => {
|
|
208
194
|
this.consumersTags = [];
|
|
209
195
|
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
210
196
|
if (!isResolved) {
|
|
211
197
|
isResolved = true;
|
|
212
198
|
reject(err);
|
|
213
|
-
this.em.emit(
|
|
199
|
+
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
214
200
|
}
|
|
215
201
|
});
|
|
216
|
-
|
|
202
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
203
|
+
// this.channel = null;
|
|
217
204
|
this.consumersTags = [];
|
|
218
205
|
debug('rabbit: connection closed');
|
|
219
206
|
if (this.options?.disableReconnect) {
|
|
@@ -224,26 +211,24 @@ class RabbitMq {
|
|
|
224
211
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
225
212
|
}
|
|
226
213
|
});
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
this.
|
|
214
|
+
this.connection.once('connect', async () => {
|
|
215
|
+
debug('rabbit: connection established');
|
|
216
|
+
this.creatingConnection = false;
|
|
217
|
+
this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
230
218
|
isResolved = true;
|
|
231
|
-
resolve(
|
|
219
|
+
resolve(connection);
|
|
232
220
|
});
|
|
233
221
|
});
|
|
234
222
|
}
|
|
235
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
223
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {} } = {}) {
|
|
236
224
|
let connection;
|
|
237
225
|
try {
|
|
238
|
-
connection = await this.getConnection(
|
|
226
|
+
connection = await this.getConnection();
|
|
239
227
|
}
|
|
240
228
|
catch (e) {
|
|
241
229
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
242
230
|
throw e;
|
|
243
231
|
}
|
|
244
|
-
if (!connection) {
|
|
245
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
246
|
-
}
|
|
247
232
|
const channel = connection.createChannel({ ...options });
|
|
248
233
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
249
234
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
@@ -259,16 +244,14 @@ class RabbitMq {
|
|
|
259
244
|
throw err;
|
|
260
245
|
}
|
|
261
246
|
}
|
|
262
|
-
async assertChannel({ force = false
|
|
263
|
-
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.channel });
|
|
247
|
+
async assertChannel({ force = false } = {}) {
|
|
264
248
|
if (!this.publishChannelSetupPromise) {
|
|
265
249
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
266
250
|
if (this.channel && !force) {
|
|
267
251
|
return resolve(this.channel);
|
|
268
252
|
}
|
|
269
253
|
try {
|
|
270
|
-
const channel = await this.getNewChannel({
|
|
271
|
-
debug('rabbit: new channel got', { connectionPurpose, channel: this.channel });
|
|
254
|
+
const channel = await this.getNewChannel({});
|
|
272
255
|
channel.on('error', (err) => {
|
|
273
256
|
logger_1.default.error('rabbit: channel error', { err });
|
|
274
257
|
});
|
|
@@ -282,8 +265,8 @@ class RabbitMq {
|
|
|
282
265
|
}
|
|
283
266
|
return this.publishChannelSetupPromise;
|
|
284
267
|
}
|
|
285
|
-
async assertExchange(exchangeName, options
|
|
286
|
-
const channel = await this.assertChannel(
|
|
268
|
+
async assertExchange(exchangeName, options) {
|
|
269
|
+
const channel = await this.assertChannel();
|
|
287
270
|
if (this.exchanges[exchangeName]) {
|
|
288
271
|
delete this.assertExchangePromises[exchangeName];
|
|
289
272
|
return this.exchanges[exchangeName];
|
|
@@ -295,30 +278,29 @@ class RabbitMq {
|
|
|
295
278
|
this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];
|
|
296
279
|
return this.exchanges[exchangeName];
|
|
297
280
|
}
|
|
298
|
-
async getQueueLength(queue
|
|
281
|
+
async getQueueLength(queue) {
|
|
299
282
|
RabbitMq.validateName('queue', queue);
|
|
300
|
-
const { connection } = this.connectionsMap[connectionPurpose];
|
|
301
283
|
const { channel } = this;
|
|
302
284
|
if (!channel) {
|
|
303
285
|
throw new Error('channel is not defined');
|
|
304
286
|
}
|
|
305
|
-
debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
|
|
287
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
306
288
|
return channel?.checkQueue(queue);
|
|
307
289
|
}
|
|
308
|
-
async deleteQueue(queue
|
|
290
|
+
async deleteQueue(queue) {
|
|
309
291
|
RabbitMq.validateName('queue', queue);
|
|
310
|
-
const channel = await this.assertChannel(
|
|
292
|
+
const channel = await this.assertChannel();
|
|
311
293
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
312
294
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
313
295
|
debug('queue deleted', deleteQueueRes);
|
|
314
296
|
return deleteQueueRes;
|
|
315
297
|
}
|
|
316
|
-
async bindQueue(queue, exchange
|
|
317
|
-
const channel = await this.assertChannel(
|
|
298
|
+
async bindQueue(queue, exchange) {
|
|
299
|
+
const channel = await this.assertChannel();
|
|
318
300
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
319
301
|
return channel.bindQueue(queue, exchange, '');
|
|
320
302
|
}
|
|
321
|
-
async setupQueue(queueName,
|
|
303
|
+
async setupQueue(queueName, options) {
|
|
322
304
|
let queue;
|
|
323
305
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
324
306
|
const localeOptions = {
|
|
@@ -331,7 +313,7 @@ class RabbitMq {
|
|
|
331
313
|
},
|
|
332
314
|
};
|
|
333
315
|
try {
|
|
334
|
-
const channel = await this.assertChannel(
|
|
316
|
+
const channel = await this.assertChannel();
|
|
335
317
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
336
318
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
337
319
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -341,8 +323,8 @@ class RabbitMq {
|
|
|
341
323
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
342
324
|
if (!this.options?.dontRetryAssert) {
|
|
343
325
|
debug('retrying assertQueue', { queueName });
|
|
344
|
-
const channel = await this.assertChannel({ force: true
|
|
345
|
-
await this.deleteQueue(queueName
|
|
326
|
+
const channel = await this.assertChannel({ force: true });
|
|
327
|
+
await this.deleteQueue(queueName);
|
|
346
328
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
347
329
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
348
330
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -366,8 +348,7 @@ class RabbitMq {
|
|
|
366
348
|
}
|
|
367
349
|
return false;
|
|
368
350
|
}
|
|
369
|
-
async assertQueue(queueName,
|
|
370
|
-
debug('rabbit: start assert queue', { connectionPurpose, queueName });
|
|
351
|
+
async assertQueue(queueName, options) {
|
|
371
352
|
RabbitMq.validateName('queue', queueName);
|
|
372
353
|
if (this.queues[queueName]) {
|
|
373
354
|
delete this.queueSetupPromises[queueName];
|
|
@@ -376,8 +357,7 @@ class RabbitMq {
|
|
|
376
357
|
if (this.queueSetupPromises[queueName]) {
|
|
377
358
|
return this.queueSetupPromises[queueName];
|
|
378
359
|
}
|
|
379
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
380
|
-
debug('rabbit: done assert queue', { connectionPurpose, queueName });
|
|
360
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
381
361
|
return this.queueSetupPromises[queueName];
|
|
382
362
|
}
|
|
383
363
|
saveConsumer(queue, callback, options) {
|
|
@@ -420,9 +400,9 @@ class RabbitMq {
|
|
|
420
400
|
}
|
|
421
401
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
422
402
|
}
|
|
423
|
-
const channel = await this.getNewChannel({
|
|
403
|
+
const channel = await this.getNewChannel({});
|
|
424
404
|
return channel.addSetup(async (confirmChannel) => {
|
|
425
|
-
const q = await this.assertQueue(queue,
|
|
405
|
+
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
426
406
|
await confirmChannel.prefetch(limit, false);
|
|
427
407
|
const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
|
|
428
408
|
if (!msg) {
|
|
@@ -504,7 +484,7 @@ class RabbitMq {
|
|
|
504
484
|
RabbitMq.validateName('queue', queue);
|
|
505
485
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
506
486
|
await this.saveConsumer(queue, callback, options);
|
|
507
|
-
const channel = await this.getNewChannel({ name: `consume
|
|
487
|
+
const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
508
488
|
return channel.addSetup(async (c) => {
|
|
509
489
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
510
490
|
await c.assertQueue(queue);
|
|
@@ -517,17 +497,16 @@ class RabbitMq {
|
|
|
517
497
|
});
|
|
518
498
|
}
|
|
519
499
|
async publish(exchange, content, customHeaders) {
|
|
520
|
-
debug('rabbit: start publish msg');
|
|
521
500
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
522
501
|
RabbitMq.validateName('exchange', exchange);
|
|
523
|
-
const channel = await this.assertChannel(
|
|
524
|
-
await this.assertExchange(exchange
|
|
502
|
+
const channel = await this.assertChannel();
|
|
503
|
+
await this.assertExchange(exchange);
|
|
525
504
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
526
505
|
});
|
|
527
506
|
}
|
|
528
507
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
529
508
|
try {
|
|
530
|
-
await this.assertChannel(
|
|
509
|
+
await this.assertChannel();
|
|
531
510
|
}
|
|
532
511
|
catch (e) {
|
|
533
512
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -535,7 +514,7 @@ class RabbitMq {
|
|
|
535
514
|
}
|
|
536
515
|
try {
|
|
537
516
|
RabbitMq.validateName('queue', queue);
|
|
538
|
-
await this.assertQueue(queue,
|
|
517
|
+
await this.assertQueue(queue, options);
|
|
539
518
|
}
|
|
540
519
|
catch (e) {
|
|
541
520
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
@@ -547,38 +526,31 @@ class RabbitMq {
|
|
|
547
526
|
return res;
|
|
548
527
|
}
|
|
549
528
|
catch (e) {
|
|
550
|
-
|
|
529
|
+
const isConnected = await this.isConnected();
|
|
530
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
551
531
|
throw e;
|
|
552
532
|
}
|
|
553
533
|
}
|
|
554
534
|
async isConnected() {
|
|
555
|
-
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
catch (e) {
|
|
575
|
-
logger_1.default.error('rabbit: isConnected - false');
|
|
576
|
-
return false;
|
|
577
|
-
}
|
|
578
|
-
logger_1.default.info('rabbit: isConnected - true');
|
|
579
|
-
return true;
|
|
580
|
-
}));
|
|
581
|
-
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
|
535
|
+
const connection = await this.getConnection();
|
|
536
|
+
const isConnected = connection.isConnected();
|
|
537
|
+
if (!isConnected) {
|
|
538
|
+
logger_1.default.error('rabbit: isConnected - false');
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
const channel = await this.assertChannel();
|
|
542
|
+
try {
|
|
543
|
+
await Promise.all([
|
|
544
|
+
channel.waitForConnect(),
|
|
545
|
+
...this.consumers.map((c) => channel.checkQueue(c.queue)),
|
|
546
|
+
]);
|
|
547
|
+
}
|
|
548
|
+
catch (e) {
|
|
549
|
+
logger_1.default.error('rabbit: isConnected - false');
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
logger_1.default.info('rabbit: isConnected - true');
|
|
553
|
+
return true;
|
|
582
554
|
}
|
|
583
555
|
async gracefulShutdown(signal) {
|
|
584
556
|
const tagsNumber = this.consumersTags.length;
|
package/dist/lib/consts.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export declare const USER_TRACING_HEADER = "x-af-user-id";
|
|
|
6
6
|
export declare const AUTOMATION_ID_HEADER = "x-af-automation-id";
|
|
7
7
|
export declare const USER_OBJECT = "userObject";
|
|
8
8
|
export declare const DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
9
|
+
export declare const CONNECTION_CREATED_CONST = "connectionCreated";
|
|
10
|
+
export declare const CONNECTION_FAILED_CONST = "connectionFailed";
|
|
9
11
|
export declare const DEFAULT_OPTIONS: {
|
|
10
12
|
limit: number;
|
|
11
13
|
retries: number;
|
|
@@ -15,7 +17,3 @@ export declare const DEFAULT_OPTIONS: {
|
|
|
15
17
|
auditContext: null;
|
|
16
18
|
enableRabbitTrace: boolean;
|
|
17
19
|
};
|
|
18
|
-
export declare enum ConnectionPurpose {
|
|
19
|
-
Consume = "consume",
|
|
20
|
-
Publish = "publish"
|
|
21
|
-
}
|
package/dist/lib/consts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DEFAULT_OPTIONS = exports.CONNECTION_FAILED_CONST = exports.CONNECTION_CREATED_CONST = exports.DEFAULT_USE_CONSUME_WITH_LOCK = exports.USER_OBJECT = exports.AUTOMATION_ID_HEADER = exports.USER_TRACING_HEADER = exports.TRACING_HEADER = exports.RETRY_HEADER = exports.DEFAULT_LOCK_TIMEOUT = exports.DEFAULT_DEAD_TTL_TWO_DAYS = void 0;
|
|
4
4
|
exports.DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 12;
|
|
5
5
|
exports.DEFAULT_LOCK_TIMEOUT = 1000 * 5;
|
|
6
6
|
exports.RETRY_HEADER = 'x-retry-count';
|
|
@@ -9,6 +9,8 @@ exports.USER_TRACING_HEADER = 'x-af-user-id';
|
|
|
9
9
|
exports.AUTOMATION_ID_HEADER = 'x-af-automation-id';
|
|
10
10
|
exports.USER_OBJECT = 'userObject';
|
|
11
11
|
exports.DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
12
|
+
exports.CONNECTION_CREATED_CONST = 'connectionCreated';
|
|
13
|
+
exports.CONNECTION_FAILED_CONST = 'connectionFailed';
|
|
12
14
|
exports.DEFAULT_OPTIONS = {
|
|
13
15
|
limit: 1,
|
|
14
16
|
retries: 1,
|
|
@@ -18,8 +20,3 @@ exports.DEFAULT_OPTIONS = {
|
|
|
18
20
|
auditContext: null,
|
|
19
21
|
enableRabbitTrace: false,
|
|
20
22
|
};
|
|
21
|
-
var ConnectionPurpose;
|
|
22
|
-
(function (ConnectionPurpose) {
|
|
23
|
-
ConnectionPurpose["Consume"] = "consume";
|
|
24
|
-
ConnectionPurpose["Publish"] = "publish";
|
|
25
|
-
})(ConnectionPurpose = exports.ConnectionPurpose || (exports.ConnectionPurpose = {}));
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
1
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
2
|
export interface ExchangesCache {
|
|
4
3
|
[key: string]: any;
|
|
@@ -42,9 +41,3 @@ export type AfConsumer = {
|
|
|
42
41
|
options: ConsumeOptions | undefined;
|
|
43
42
|
};
|
|
44
43
|
export declare const CONSUMER_DEFAULT_OPTIONS: Options.Consume;
|
|
45
|
-
export type ConnectionData = {
|
|
46
|
-
connection: AmqpConnectionManager | null;
|
|
47
|
-
creatingConnection: boolean;
|
|
48
|
-
connectionCreatedEventName: string;
|
|
49
|
-
connectionFailedEventName: string;
|
|
50
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/rabbit",
|
|
3
|
-
"version": "3.2.24-beta.
|
|
3
|
+
"version": "3.2.24-beta.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"redis-lock": "^0.1.4"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@autofleet/logger": "*"
|
|
30
|
+
"@autofleet/logger": "*",
|
|
31
|
+
"@autofleet/zehut": "*"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@autofleet/logger": "4.0.6",
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,8 @@ import getRedisInstance, { RedisConfig } from './lib/redis';
|
|
|
20
20
|
import { assertExchangeFanout, rand, wrapSetImmediate } from './lib/utils';
|
|
21
21
|
import {
|
|
22
22
|
AUTOMATION_ID_HEADER,
|
|
23
|
-
|
|
23
|
+
CONNECTION_CREATED_CONST,
|
|
24
|
+
CONNECTION_FAILED_CONST,
|
|
24
25
|
DEFAULT_LOCK_TIMEOUT,
|
|
25
26
|
DEFAULT_OPTIONS,
|
|
26
27
|
RETRY_HEADER,
|
|
@@ -39,13 +40,13 @@ import {
|
|
|
39
40
|
CONSUMER_DEFAULT_OPTIONS,
|
|
40
41
|
QueueSetupPromisesDictionary,
|
|
41
42
|
AssertExchangePromisesDictionary,
|
|
42
|
-
ConnectionData,
|
|
43
43
|
} from './lib/types';
|
|
44
44
|
|
|
45
45
|
// const debug = nodeDebug('af-rabbitmq')
|
|
46
46
|
const debug = logger.debug.bind(logger);
|
|
47
47
|
|
|
48
48
|
const PUBLISH_TIMEOUT = 1000 * 10;
|
|
49
|
+
|
|
49
50
|
export interface IAfRabbitMq {
|
|
50
51
|
ack: any;
|
|
51
52
|
nack: any;
|
|
@@ -85,13 +86,11 @@ type newChannelOpts = {
|
|
|
85
86
|
name?: string;
|
|
86
87
|
onClose?: null | ((args: any | null) => void);
|
|
87
88
|
options?: CreateChannelOpts | undefined;
|
|
88
|
-
connectionPurpose?: ConnectionPurpose,
|
|
89
89
|
};
|
|
90
90
|
|
|
91
91
|
type assertChannelOpts = {
|
|
92
92
|
channelName?: string;
|
|
93
93
|
force?: boolean;
|
|
94
|
-
connectionPurpose?: ConnectionPurpose;
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
type AfConsumer = {
|
|
@@ -103,7 +102,7 @@ type AfConsumer = {
|
|
|
103
102
|
const HEARTBEAT = '60';
|
|
104
103
|
|
|
105
104
|
class RabbitMq implements IAfRabbitMq {
|
|
106
|
-
static parseMsg(msg: any): any {
|
|
105
|
+
static parseMsg(msg: any) : any {
|
|
107
106
|
let { content } = msg;
|
|
108
107
|
content = content.toString();
|
|
109
108
|
|
|
@@ -148,15 +147,14 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
148
147
|
|
|
149
148
|
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
150
149
|
|
|
151
|
-
blockReconnect: boolean | null | undefined
|
|
150
|
+
blockReconnect: boolean | null | undefined
|
|
152
151
|
|
|
153
|
-
|
|
154
|
-
[ConnectionPurpose.Consume]: ConnectionData;
|
|
155
|
-
[ConnectionPurpose.Publish]: ConnectionData;
|
|
156
|
-
};
|
|
152
|
+
connection: AmqpConnectionManager | null | undefined
|
|
157
153
|
|
|
158
154
|
em: EventEmitter;
|
|
159
155
|
|
|
156
|
+
creatingConnection: boolean;
|
|
157
|
+
|
|
160
158
|
exchanges: ExchangesCache;
|
|
161
159
|
|
|
162
160
|
queues: QueuesCache;
|
|
@@ -180,20 +178,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
180
178
|
this.em = new EventEmitter();
|
|
181
179
|
this.channel = null;
|
|
182
180
|
this.publishChannelSetupPromise = null;
|
|
183
|
-
this.
|
|
184
|
-
|
|
185
|
-
connection: null,
|
|
186
|
-
creatingConnection: false,
|
|
187
|
-
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
188
|
-
connectionFailedEventName: 'consumeConnectionFailed',
|
|
189
|
-
},
|
|
190
|
-
[ConnectionPurpose.Publish]: {
|
|
191
|
-
connection: null,
|
|
192
|
-
creatingConnection: false,
|
|
193
|
-
connectionCreatedEventName: 'publishConnectionCreated',
|
|
194
|
-
connectionFailedEventName: 'publishConnectionFailed',
|
|
195
|
-
},
|
|
196
|
-
};
|
|
181
|
+
this.connection = null;
|
|
182
|
+
this.creatingConnection = false;
|
|
197
183
|
this.exchanges = {};
|
|
198
184
|
this.queues = {};
|
|
199
185
|
this.queueSetupPromises = {};
|
|
@@ -230,7 +216,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
230
216
|
return false;
|
|
231
217
|
}
|
|
232
218
|
|
|
233
|
-
public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage): Promise<any> => {
|
|
219
|
+
public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage) : Promise<any> => {
|
|
234
220
|
if (msg) {
|
|
235
221
|
debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });
|
|
236
222
|
await channel.ack(msg);
|
|
@@ -256,8 +242,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
256
242
|
userMsg: ConsumeMessageOrNull,
|
|
257
243
|
{
|
|
258
244
|
skipRetry = false,
|
|
259
|
-
}: NackOptions = {},
|
|
260
|
-
): Promise<any> => {
|
|
245
|
+
}: NackOptions = { },
|
|
246
|
+
) : Promise<any> => {
|
|
261
247
|
await this.unlockRedisIfNeeded(releaseLock);
|
|
262
248
|
if (channel && msg) {
|
|
263
249
|
if (
|
|
@@ -291,36 +277,30 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
291
277
|
}
|
|
292
278
|
}
|
|
293
279
|
|
|
294
|
-
async getConnection(
|
|
295
|
-
return new Promise<AmqpConnectionManager
|
|
296
|
-
const {
|
|
297
|
-
connection,
|
|
298
|
-
creatingConnection,
|
|
299
|
-
connectionCreatedEventName,
|
|
300
|
-
connectionFailedEventName,
|
|
301
|
-
} = this.connectionsMap[connectionPurpose];
|
|
280
|
+
async getConnection() {
|
|
281
|
+
return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
|
|
302
282
|
if (this.blockReconnect) {
|
|
303
283
|
debug('rabbit: block reconnect');
|
|
304
284
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
305
285
|
// @ts-ignore
|
|
306
286
|
return resolve();
|
|
307
287
|
}
|
|
308
|
-
if (connection !== null) {
|
|
309
|
-
if (this.options?.disableReconnect || connection?.isConnected()) {
|
|
288
|
+
if (this.connection !== null) {
|
|
289
|
+
if (this.options?.disableReconnect || this.connection?.isConnected()) {
|
|
310
290
|
debug('rabbit: connection - is connected');
|
|
311
291
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
312
292
|
// @ts-ignore
|
|
313
|
-
return resolve(connection);
|
|
293
|
+
return resolve(this.connection);
|
|
314
294
|
}
|
|
315
295
|
debug('rabbit: connection - reconnecting');
|
|
316
296
|
}
|
|
317
|
-
if (creatingConnection) {
|
|
297
|
+
if (this.creatingConnection) {
|
|
318
298
|
debug('rabbit: creating connection emi');
|
|
319
|
-
this.em.once(
|
|
320
|
-
this.em.once(
|
|
299
|
+
this.em.once(CONNECTION_CREATED_CONST, resolve);
|
|
300
|
+
this.em.once(CONNECTION_FAILED_CONST, reject);
|
|
321
301
|
return;
|
|
322
302
|
}
|
|
323
|
-
this.
|
|
303
|
+
this.creatingConnection = true;
|
|
324
304
|
let isResolved = false;
|
|
325
305
|
|
|
326
306
|
// It is import to use it as a function and not as a variable
|
|
@@ -337,33 +317,32 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
337
317
|
};
|
|
338
318
|
|
|
339
319
|
const defaultUrls = findServers();
|
|
340
|
-
const
|
|
320
|
+
const connection: AmqpConnectionManager = await connect(defaultUrls, {
|
|
341
321
|
findServers,
|
|
342
322
|
});
|
|
343
323
|
|
|
344
|
-
this.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
newConnection.on('error', (err) => {
|
|
324
|
+
this.connection = connection;
|
|
325
|
+
this.connection.on('error', (err) => {
|
|
348
326
|
logger.error('rabbit: connection error', { err });
|
|
349
327
|
if (!isResolved) {
|
|
350
328
|
isResolved = true;
|
|
351
329
|
reject(err);
|
|
352
|
-
this.em.emit(
|
|
330
|
+
this.em.emit(CONNECTION_FAILED_CONST, err);
|
|
353
331
|
}
|
|
354
332
|
});
|
|
355
333
|
|
|
356
|
-
|
|
334
|
+
this.connection.on('connectFailed', (err) => {
|
|
357
335
|
this.consumersTags = [];
|
|
358
336
|
logger.error('rabbit: connection connectFailed', { err });
|
|
359
337
|
if (!isResolved) {
|
|
360
338
|
isResolved = true;
|
|
361
339
|
reject(err);
|
|
362
|
-
this.em.emit(
|
|
340
|
+
this.em.emit(CONNECTION_FAILED_CONST, err);
|
|
363
341
|
}
|
|
364
342
|
});
|
|
365
343
|
|
|
366
|
-
|
|
344
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
345
|
+
// this.channel = null;
|
|
367
346
|
this.consumersTags = [];
|
|
368
347
|
debug('rabbit: connection closed');
|
|
369
348
|
if (this.options?.disableReconnect) {
|
|
@@ -373,28 +352,25 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
373
352
|
logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
374
353
|
}
|
|
375
354
|
});
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
355
|
+
|
|
356
|
+
this.connection.once('connect', async () => {
|
|
357
|
+
debug('rabbit: connection established');
|
|
358
|
+
this.creatingConnection = false;
|
|
359
|
+
this.em.emit(CONNECTION_CREATED_CONST, connection);
|
|
379
360
|
isResolved = true;
|
|
380
|
-
resolve(
|
|
361
|
+
resolve(connection);
|
|
381
362
|
});
|
|
382
363
|
});
|
|
383
364
|
}
|
|
384
365
|
|
|
385
|
-
async getNewChannel({
|
|
386
|
-
|
|
387
|
-
}: newChannelOpts): Promise<ChannelWrapper> {
|
|
388
|
-
let connection!: AmqpConnectionManager | undefined | null;
|
|
366
|
+
async getNewChannel({ name = rand().toString(), onClose = null, options = {} }: newChannelOpts = {}) {
|
|
367
|
+
let connection!: AmqpConnectionManager;
|
|
389
368
|
try {
|
|
390
|
-
connection = await this.getConnection(
|
|
369
|
+
connection = await this.getConnection();
|
|
391
370
|
} catch (e) {
|
|
392
371
|
logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
393
372
|
throw e;
|
|
394
373
|
}
|
|
395
|
-
if (!connection) {
|
|
396
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
397
|
-
}
|
|
398
374
|
const channel = connection.createChannel({ ...options });
|
|
399
375
|
once(channel, 'close').then((args) => {
|
|
400
376
|
logger.error(`rabbit: channel ${name} closed`);
|
|
@@ -410,8 +386,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
410
386
|
}
|
|
411
387
|
}
|
|
412
388
|
|
|
413
|
-
async assertChannel({ force = false
|
|
414
|
-
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.channel });
|
|
389
|
+
async assertChannel({ force = false } : assertChannelOpts = {}): Promise<ChannelWrapper> {
|
|
415
390
|
if (!this.publishChannelSetupPromise) {
|
|
416
391
|
this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
|
|
417
392
|
if (this.channel && !force) {
|
|
@@ -419,8 +394,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
419
394
|
}
|
|
420
395
|
|
|
421
396
|
try {
|
|
422
|
-
const channel = await this.getNewChannel({
|
|
423
|
-
debug('rabbit: new channel got', { connectionPurpose, channel: this.channel });
|
|
397
|
+
const channel = await this.getNewChannel({});
|
|
424
398
|
channel.on('error', (err) => {
|
|
425
399
|
logger.error('rabbit: channel error', { err });
|
|
426
400
|
});
|
|
@@ -434,8 +408,9 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
434
408
|
return this.publishChannelSetupPromise;
|
|
435
409
|
}
|
|
436
410
|
|
|
437
|
-
async assertExchange(exchangeName: string, options
|
|
438
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
411
|
+
async assertExchange(exchangeName: string, options?: any) {
|
|
412
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
413
|
+
|
|
439
414
|
if (this.exchanges[exchangeName]) {
|
|
440
415
|
delete this.assertExchangePromises[exchangeName];
|
|
441
416
|
return this.exchanges[exchangeName];
|
|
@@ -450,33 +425,32 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
450
425
|
return this.exchanges[exchangeName];
|
|
451
426
|
}
|
|
452
427
|
|
|
453
|
-
async getQueueLength(queue: string
|
|
428
|
+
async getQueueLength(queue: string) {
|
|
454
429
|
RabbitMq.validateName('queue', queue);
|
|
455
|
-
const { connection } = this.connectionsMap[connectionPurpose];
|
|
456
430
|
const { channel } = this;
|
|
457
431
|
if (!channel) {
|
|
458
432
|
throw new Error('channel is not defined');
|
|
459
433
|
}
|
|
460
|
-
debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
|
|
434
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
461
435
|
return channel?.checkQueue(queue);
|
|
462
436
|
}
|
|
463
437
|
|
|
464
|
-
private async deleteQueue(queue: string
|
|
438
|
+
private async deleteQueue(queue: string) {
|
|
465
439
|
RabbitMq.validateName('queue', queue);
|
|
466
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
440
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
467
441
|
logger.info('rabbit: deleting queue', { queue });
|
|
468
442
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
469
443
|
debug('queue deleted', deleteQueueRes);
|
|
470
444
|
return deleteQueueRes;
|
|
471
445
|
}
|
|
472
446
|
|
|
473
|
-
async bindQueue(queue: string, exchange: string
|
|
474
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
447
|
+
async bindQueue(queue: string, exchange: string) {
|
|
448
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
475
449
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
476
450
|
return channel.bindQueue(queue, exchange, '');
|
|
477
451
|
}
|
|
478
452
|
|
|
479
|
-
async setupQueue(queueName: string,
|
|
453
|
+
async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
480
454
|
let queue: Replies.AssertQueue;
|
|
481
455
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
482
456
|
const localeOptions = {
|
|
@@ -489,7 +463,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
489
463
|
},
|
|
490
464
|
};
|
|
491
465
|
try {
|
|
492
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
466
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
493
467
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
494
468
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
495
469
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -498,8 +472,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
498
472
|
logger.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
499
473
|
if (!this.options?.dontRetryAssert) {
|
|
500
474
|
debug('retrying assertQueue', { queueName });
|
|
501
|
-
const channel = await this.assertChannel({ force: true
|
|
502
|
-
await this.deleteQueue(queueName
|
|
475
|
+
const channel = await this.assertChannel({ force: true });
|
|
476
|
+
await this.deleteQueue(queueName);
|
|
503
477
|
|
|
504
478
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
505
479
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
@@ -529,8 +503,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
529
503
|
return false;
|
|
530
504
|
}
|
|
531
505
|
|
|
532
|
-
async assertQueue(queueName: string,
|
|
533
|
-
debug('rabbit: start assert queue', { connectionPurpose, queueName });
|
|
506
|
+
async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any> {
|
|
534
507
|
RabbitMq.validateName('queue', queueName);
|
|
535
508
|
if (this.queues[queueName]) {
|
|
536
509
|
delete this.queueSetupPromises[queueName];
|
|
@@ -541,13 +514,12 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
541
514
|
return this.queueSetupPromises[queueName];
|
|
542
515
|
}
|
|
543
516
|
|
|
544
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
545
|
-
debug('rabbit: done assert queue', { connectionPurpose, queueName });
|
|
517
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
546
518
|
return this.queueSetupPromises[queueName];
|
|
547
519
|
}
|
|
548
520
|
|
|
549
521
|
private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined) {
|
|
550
|
-
const isConsumerExist:
|
|
522
|
+
const isConsumerExist :boolean = this.consumers.some((consumer) => consumer.queue === queue);
|
|
551
523
|
if (!isConsumerExist) {
|
|
552
524
|
logger.info(`rabbit: consumer: ${queue} saved in consumer array`);
|
|
553
525
|
this.consumers.push({
|
|
@@ -596,9 +568,9 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
596
568
|
}
|
|
597
569
|
logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
598
570
|
}
|
|
599
|
-
const channel = await this.getNewChannel({
|
|
571
|
+
const channel = await this.getNewChannel({});
|
|
600
572
|
return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
|
|
601
|
-
const q = await this.assertQueue(queue,
|
|
573
|
+
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
602
574
|
await confirmChannel.prefetch(limit, false);
|
|
603
575
|
const { consumerTag } = await confirmChannel.consume(
|
|
604
576
|
queue,
|
|
@@ -686,13 +658,13 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
686
658
|
});
|
|
687
659
|
}
|
|
688
660
|
|
|
689
|
-
async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
|
|
661
|
+
async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<any> {
|
|
690
662
|
const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };
|
|
691
663
|
RabbitMq.validateName('exchange', exchange);
|
|
692
664
|
RabbitMq.validateName('queue', queue);
|
|
693
665
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
694
666
|
await this.saveConsumer(queue, callback, options);
|
|
695
|
-
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume
|
|
667
|
+
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
696
668
|
|
|
697
669
|
return channel.addSetup(async (c: ConfirmChannel) => {
|
|
698
670
|
const assertExchange = await assertExchangeFanout(c, exchange);
|
|
@@ -710,12 +682,11 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
710
682
|
});
|
|
711
683
|
}
|
|
712
684
|
|
|
713
|
-
async publish(exchange: string, content: any, customHeaders?: any): Promise<boolean> {
|
|
714
|
-
debug('rabbit: start publish msg');
|
|
685
|
+
async publish(exchange: string, content: any, customHeaders?: any) : Promise<boolean> {
|
|
715
686
|
return wrapSetImmediate(async () => {
|
|
716
687
|
RabbitMq.validateName('exchange', exchange);
|
|
717
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
718
|
-
await this.assertExchange(exchange
|
|
688
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
689
|
+
await this.assertExchange(exchange);
|
|
719
690
|
await channel.publish(exchange, '',
|
|
720
691
|
Buffer.from(JSON.stringify(content)),
|
|
721
692
|
RabbitMq.getPublishOptions(customHeaders));
|
|
@@ -729,7 +700,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
729
700
|
customHeaders?: any,
|
|
730
701
|
): Promise<boolean | undefined> {
|
|
731
702
|
try {
|
|
732
|
-
await this.assertChannel(
|
|
703
|
+
await this.assertChannel();
|
|
733
704
|
} catch (e) {
|
|
734
705
|
logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
735
706
|
throw e;
|
|
@@ -737,7 +708,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
737
708
|
|
|
738
709
|
try {
|
|
739
710
|
RabbitMq.validateName('queue', queue);
|
|
740
|
-
await this.assertQueue(queue,
|
|
711
|
+
await this.assertQueue(queue, options);
|
|
741
712
|
} catch (e) {
|
|
742
713
|
logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
743
714
|
throw e;
|
|
@@ -750,43 +721,34 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
750
721
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
751
722
|
return res;
|
|
752
723
|
} catch (e) {
|
|
753
|
-
|
|
724
|
+
const isConnected = await this.isConnected();
|
|
725
|
+
logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
754
726
|
throw e;
|
|
755
727
|
}
|
|
756
728
|
}
|
|
757
729
|
|
|
758
|
-
async isConnected(): Promise<boolean> {
|
|
759
|
-
|
|
760
|
-
const
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
]);
|
|
778
|
-
} catch (e) {
|
|
779
|
-
logger.error('rabbit: isConnected - false');
|
|
780
|
-
return false;
|
|
781
|
-
}
|
|
782
|
-
logger.info('rabbit: isConnected - true');
|
|
783
|
-
return true;
|
|
784
|
-
}),
|
|
785
|
-
);
|
|
786
|
-
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
|
730
|
+
async isConnected() : Promise<boolean> {
|
|
731
|
+
const connection = await this.getConnection();
|
|
732
|
+
const isConnected = connection.isConnected();
|
|
733
|
+
if (!isConnected) {
|
|
734
|
+
logger.error('rabbit: isConnected - false');
|
|
735
|
+
return false;
|
|
736
|
+
}
|
|
737
|
+
const channel: any = await this.assertChannel();
|
|
738
|
+
try {
|
|
739
|
+
await Promise.all([
|
|
740
|
+
channel.waitForConnect(),
|
|
741
|
+
...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
|
|
742
|
+
]);
|
|
743
|
+
} catch (e) {
|
|
744
|
+
logger.error('rabbit: isConnected - false');
|
|
745
|
+
return false;
|
|
746
|
+
}
|
|
747
|
+
logger.info('rabbit: isConnected - true');
|
|
748
|
+
return true;
|
|
787
749
|
}
|
|
788
750
|
|
|
789
|
-
async gracefulShutdown(signal: string): Promise<void> {
|
|
751
|
+
async gracefulShutdown(signal: string) : Promise<void> {
|
|
790
752
|
const tagsNumber = this.consumersTags.length;
|
|
791
753
|
logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);
|
|
792
754
|
const cancelTagPromises = this.consumersTags.map(([channel, tag]) => channel.cancel(tag));
|
package/src/lib/consts.ts
CHANGED
|
@@ -6,6 +6,8 @@ export const USER_TRACING_HEADER = 'x-af-user-id';
|
|
|
6
6
|
export const AUTOMATION_ID_HEADER = 'x-af-automation-id';
|
|
7
7
|
export const USER_OBJECT = 'userObject';
|
|
8
8
|
export const DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
9
|
+
export const CONNECTION_CREATED_CONST = 'connectionCreated';
|
|
10
|
+
export const CONNECTION_FAILED_CONST = 'connectionFailed';
|
|
9
11
|
export const DEFAULT_OPTIONS = {
|
|
10
12
|
limit: 1,
|
|
11
13
|
retries: 1,
|
|
@@ -15,8 +17,3 @@ export const DEFAULT_OPTIONS = {
|
|
|
15
17
|
auditContext: null,
|
|
16
18
|
enableRabbitTrace: false,
|
|
17
19
|
};
|
|
18
|
-
|
|
19
|
-
export enum ConnectionPurpose {
|
|
20
|
-
Consume = 'consume',
|
|
21
|
-
Publish = 'publish',
|
|
22
|
-
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
1
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
2
|
|
|
4
3
|
export interface ExchangesCache {
|
|
@@ -60,10 +59,3 @@ export const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {
|
|
|
60
59
|
[HA_PROMOTE_ON_SHUTDOWN]: 'always',
|
|
61
60
|
},
|
|
62
61
|
};
|
|
63
|
-
|
|
64
|
-
export type ConnectionData = {
|
|
65
|
-
connection: AmqpConnectionManager | null;
|
|
66
|
-
creatingConnection: boolean;
|
|
67
|
-
connectionCreatedEventName: string;
|
|
68
|
-
connectionFailedEventName: string;
|
|
69
|
-
};
|