@autofleet/rabbit 3.2.24-beta.10 → 3.2.24-beta.2

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