@autofleet/rabbit 3.2.19-beta.6 → 3.2.19-beta.8

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,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 { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary } from './lib/types';
6
+ import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, ConnectionRole } from './lib/types';
7
7
  export interface IAfRabbitMq {
8
8
  ack: any;
9
9
  nack: any;
@@ -37,10 +37,12 @@ type newChannelOpts = {
37
37
  name?: string;
38
38
  onClose?: null | ((args: any | null) => void);
39
39
  options?: CreateChannelOpts | undefined;
40
+ connectionRole: ConnectionRole;
40
41
  };
41
42
  type assertChannelOpts = {
42
43
  channelName?: string;
43
44
  force?: boolean;
45
+ connectionRole: ConnectionRole;
44
46
  };
45
47
  declare class RabbitMq implements IAfRabbitMq {
46
48
  static parseMsg(msg: any): any;
@@ -58,10 +60,13 @@ declare class RabbitMq implements IAfRabbitMq {
58
60
  DISCONNECT_MSG: string;
59
61
  RECONNECT_MSG: string;
60
62
  channel: ChannelWrapper | null;
63
+ publishChannelSetupPromise: Promise<ChannelWrapper> | null;
61
64
  blockReconnect: boolean | null | undefined;
62
- connection: AmqpConnectionManager | null | undefined;
65
+ consumeConnection: AmqpConnectionManager | null | undefined;
66
+ publishConnection: AmqpConnectionManager | null | undefined;
63
67
  em: EventEmitter;
64
- creatingConnection: boolean;
68
+ creatingConsumeConnection: boolean;
69
+ creatingPublishConnection: boolean;
65
70
  exchanges: ExchangesCache;
66
71
  queues: QueuesCache;
67
72
  queueSetupPromises: QueueSetupPromisesDictionary;
@@ -75,15 +80,19 @@ declare class RabbitMq implements IAfRabbitMq {
75
80
  private shouldConsumeMessageByTimestamp;
76
81
  ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
77
82
  nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
78
- getConnection(): Promise<AmqpConnectionManager>;
79
- getNewChannel({ name, onClose, options }?: newChannelOpts): Promise<ChannelWrapper>;
80
- assertChannel({ force }?: assertChannelOpts): Promise<ChannelWrapper>;
83
+ geConnectionByRole: (connectionRole: ConnectionRole) => {
84
+ connectionByRole: AmqpConnectionManager | null | undefined;
85
+ creatingConnectionByRole: boolean;
86
+ };
87
+ getConnection(connectionRole: ConnectionRole): Promise<AmqpConnectionManager | null | undefined>;
88
+ getNewChannel({ name, onClose, options, connectionRole, }?: newChannelOpts): Promise<ChannelWrapper>;
89
+ assertChannel({ force, connectionRole }?: assertChannelOpts): Promise<ChannelWrapper>;
81
90
  assertExchange(exchangeName: string, options?: any): Promise<any>;
82
- getQueueLength(queue: string): Promise<Replies.AssertQueue>;
91
+ getQueueLength(queue: string, connectionRole?: ConnectionRole): Promise<Replies.AssertQueue>;
83
92
  private deleteQueue;
84
- bindQueue(queue: string, exchange: string): Promise<void>;
85
- setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
86
- assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
93
+ bindQueue(queue: string, exchange: string, connectionRole: ConnectionRole): Promise<void>;
94
+ setupQueue(queueName: string, connectionRole: ConnectionRole, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
95
+ assertQueue(queueName: string, connectionRole: ConnectionRole, options?: Options.AssertQueue): Promise<any>;
87
96
  private saveConsumer;
88
97
  consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
89
98
  private lockRedisIfNeeded;
@@ -91,8 +100,8 @@ declare class RabbitMq implements IAfRabbitMq {
91
100
  private consumeFromRabbit;
92
101
  consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
93
102
  publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
94
- sendToQueue(queue: string, content: any, options?: any, customHeaders?: any, isBlocking?: boolean): Promise<boolean | undefined>;
95
- isConnected(): Promise<boolean>;
103
+ sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean | undefined>;
104
+ isConnected(connectionRole: ConnectionRole): Promise<boolean>;
96
105
  gracefulShutdown(signal: string): Promise<void>;
97
106
  }
98
107
  export default RabbitMq;
package/dist/index.js CHANGED
@@ -115,10 +115,16 @@ class RabbitMq {
115
115
  });
116
116
  }
117
117
  };
118
+ this.geConnectionByRole = (connectionRole) => (connectionRole === types_1.ConnectionRole.Consumer
119
+ ? { connectionByRole: this.consumeConnection, creatingConnectionByRole: this.creatingConsumeConnection }
120
+ : { connectionByRole: this.publishConnection, creatingConnectionByRole: this.creatingPublishConnection });
118
121
  this.em = new events_1.EventEmitter();
119
122
  this.channel = null;
120
- this.connection = null;
121
- this.creatingConnection = false;
123
+ this.publishChannelSetupPromise = null;
124
+ this.consumeConnection = null;
125
+ this.publishConnection = null;
126
+ this.creatingPublishConnection = false;
127
+ this.creatingConsumeConnection = false;
122
128
  this.exchanges = {};
123
129
  this.queues = {};
124
130
  this.queueSetupPromises = {};
@@ -139,30 +145,36 @@ class RabbitMq {
139
145
  });
140
146
  }
141
147
  }
142
- async getConnection() {
148
+ async getConnection(connectionRole) {
143
149
  return new Promise(async (resolve, reject) => {
150
+ const { connectionByRole, creatingConnectionByRole } = this.geConnectionByRole(connectionRole);
144
151
  if (this.blockReconnect) {
145
152
  debug('rabbit: block reconnect');
146
153
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
147
154
  // @ts-ignore
148
155
  return resolve();
149
156
  }
150
- if (this.connection !== null) {
151
- if (this.options?.disableReconnect || this.connection?.isConnected()) {
157
+ if (connectionByRole !== null) {
158
+ if (this.options?.disableReconnect || connectionByRole?.isConnected()) {
152
159
  debug('rabbit: connection - is connected');
153
160
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
154
161
  // @ts-ignore
155
- return resolve(this.connection);
162
+ return resolve(connectionByRole);
156
163
  }
157
164
  debug('rabbit: connection - reconnecting');
158
165
  }
159
- if (this.creatingConnection) {
166
+ if (creatingConnectionByRole) {
160
167
  debug('rabbit: creating connection emi');
161
168
  this.em.once(consts_1.CONNECTION_CREATED_CONST, resolve);
162
169
  this.em.once(consts_1.CONNECTION_FAILED_CONST, reject);
163
170
  return;
164
171
  }
165
- this.creatingConnection = true;
172
+ if (connectionRole === types_1.ConnectionRole.Consumer) {
173
+ this.creatingConsumeConnection = true;
174
+ }
175
+ else {
176
+ this.creatingPublishConnection = true;
177
+ }
166
178
  let isResolved = false;
167
179
  // It is import to use it as a function and not as a variable
168
180
  // because of k8s changes the env variables
@@ -175,11 +187,20 @@ class RabbitMq {
175
187
  return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
176
188
  };
177
189
  const defaultUrls = findServers();
178
- const connection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
190
+ const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
179
191
  findServers,
180
192
  });
181
- this.connection = connection;
182
- this.connection.on('error', (err) => {
193
+ if (!newConnection) {
194
+ logger_1.default.error('rabbit: couldnt create a connection');
195
+ return resolve(connectionByRole);
196
+ }
197
+ if (connectionRole === types_1.ConnectionRole.Consumer) {
198
+ this.consumeConnection = newConnection;
199
+ }
200
+ else {
201
+ this.publishConnection = newConnection;
202
+ }
203
+ newConnection.on('error', (err) => {
183
204
  logger_1.default.error('rabbit: connection error', { err });
184
205
  if (!isResolved) {
185
206
  isResolved = true;
@@ -187,7 +208,7 @@ class RabbitMq {
187
208
  this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
188
209
  }
189
210
  });
190
- this.connection.on('connectFailed', (err) => {
211
+ newConnection.on('connectFailed', (err) => {
191
212
  this.consumersTags = [];
192
213
  logger_1.default.error('rabbit: connection connectFailed', { err });
193
214
  if (!isResolved) {
@@ -196,7 +217,7 @@ class RabbitMq {
196
217
  this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
197
218
  }
198
219
  });
199
- this.connection.on('disconnect', ({ err }) => {
220
+ newConnection.on('disconnect', ({ err }) => {
200
221
  this.consumersTags = [];
201
222
  debug('rabbit: connection closed');
202
223
  if (this.options?.disableReconnect) {
@@ -207,24 +228,32 @@ class RabbitMq {
207
228
  logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
208
229
  }
209
230
  });
210
- this.connection.once('connect', async () => {
231
+ newConnection.once('connect', async () => {
211
232
  debug('rabbit: connection established');
212
- this.creatingConnection = false;
213
- this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
233
+ if (connectionRole === types_1.ConnectionRole.Consumer) {
234
+ this.creatingConsumeConnection = false;
235
+ }
236
+ else {
237
+ this.creatingPublishConnection = false;
238
+ }
239
+ this.em.emit(consts_1.CONNECTION_CREATED_CONST, newConnection);
214
240
  isResolved = true;
215
- resolve(connection);
241
+ resolve(newConnection);
216
242
  });
217
243
  });
218
244
  }
219
- async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {} } = {}) {
245
+ async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connectionRole, } = { connectionRole: types_1.ConnectionRole.Consumer }) {
220
246
  let connection;
221
247
  try {
222
- connection = await this.getConnection();
248
+ connection = await this.getConnection(connectionRole);
223
249
  }
224
250
  catch (e) {
225
251
  logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
226
252
  throw e;
227
253
  }
254
+ if (!connection) {
255
+ throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
256
+ }
228
257
  const channel = connection.createChannel({ ...options });
229
258
  (0, events_1.once)(channel, 'close').then((args) => {
230
259
  logger_1.default.error(`rabbit: channel ${name} closed`);
@@ -240,26 +269,29 @@ class RabbitMq {
240
269
  throw err;
241
270
  }
242
271
  }
243
- async assertChannel({ force = false } = {}) {
244
- return new Promise(async (resolve, reject) => {
245
- if (this.channel && !force) {
246
- return resolve(this.channel);
247
- }
248
- try {
249
- const channel = await this.getNewChannel({});
250
- channel.on('error', (err) => {
251
- logger_1.default.error('rabbit: channel error', { err });
252
- });
253
- this.channel = channel;
254
- resolve(channel);
255
- }
256
- catch (e) {
257
- reject(e);
258
- }
259
- });
272
+ async assertChannel({ force = false, connectionRole } = { connectionRole: types_1.ConnectionRole.Consumer }) {
273
+ if (!this.publishChannelSetupPromise) {
274
+ this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
275
+ if (this.channel && !force) {
276
+ return resolve(this.channel);
277
+ }
278
+ try {
279
+ const channel = await this.getNewChannel({ connectionRole });
280
+ channel.on('error', (err) => {
281
+ logger_1.default.error('rabbit: channel error', { err });
282
+ });
283
+ this.channel = channel;
284
+ resolve(channel);
285
+ }
286
+ catch (e) {
287
+ reject(e);
288
+ }
289
+ });
290
+ }
291
+ return this.publishChannelSetupPromise;
260
292
  }
261
293
  async assertExchange(exchangeName, options) {
262
- const channel = await this.assertChannel();
294
+ const channel = await this.assertChannel({ connectionRole: options.connectionRole });
263
295
  if (this.exchanges[exchangeName]) {
264
296
  return this.exchanges[exchangeName];
265
297
  }
@@ -267,32 +299,33 @@ class RabbitMq {
267
299
  this.exchanges[exchangeName] = exchange;
268
300
  return exchange;
269
301
  }
270
- async getQueueLength(queue) {
302
+ async getQueueLength(queue, connectionRole = types_1.ConnectionRole.Consumer) {
271
303
  RabbitMq.validateName('queue', queue);
304
+ const { connectionByRole } = this.geConnectionByRole(connectionRole);
272
305
  const { channel } = this;
273
306
  if (!channel) {
274
307
  throw new Error('channel is not defined');
275
308
  }
276
- debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
309
+ debug('rabbit: getting queue length', { queue, connected: connectionByRole?.isConnected() });
277
310
  return channel?.checkQueue(queue);
278
311
  }
279
- async deleteQueue(queue) {
312
+ async deleteQueue(queue, connectionRole) {
280
313
  RabbitMq.validateName('queue', queue);
281
- const channel = await this.assertChannel();
314
+ const channel = await this.assertChannel({ connectionRole });
282
315
  logger_1.default.info('rabbit: deleting queue', { queue });
283
316
  const deleteQueueRes = await channel.deleteQueue(queue);
284
317
  debug('queue deleted', deleteQueueRes);
285
318
  return deleteQueueRes;
286
319
  }
287
- async bindQueue(queue, exchange) {
288
- const channel = await this.assertChannel();
320
+ async bindQueue(queue, exchange, connectionRole) {
321
+ const channel = await this.assertChannel({ connectionRole });
289
322
  await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
290
323
  return channel.bindQueue(queue, exchange, '');
291
324
  }
292
- async setupQueue(queueName, options) {
325
+ async setupQueue(queueName, connectionRole, options) {
293
326
  let queue;
294
327
  try {
295
- const channel = await this.assertChannel();
328
+ const channel = await this.assertChannel({ connectionRole });
296
329
  debug('assertQueue->channel.addSetup', { queueName });
297
330
  await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
298
331
  debug('assertQueue->channel.assertQueue', { queueName });
@@ -302,8 +335,8 @@ class RabbitMq {
302
335
  logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
303
336
  if (!this.options?.dontRetryAssert) {
304
337
  debug('retrying assertQueue', { queueName });
305
- const channel = await this.assertChannel({ force: true });
306
- await this.deleteQueue(queueName);
338
+ const channel = await this.assertChannel({ force: true, connectionRole });
339
+ await this.deleteQueue(queueName, connectionRole);
307
340
  debug('retrying assertQueue->channel.addSetup', { queueName });
308
341
  await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
309
342
  debug('retrying assertQueue->channel.assertQueue', { queueName });
@@ -316,7 +349,7 @@ class RabbitMq {
316
349
  this.queues[queueName] = queueName;
317
350
  return queue;
318
351
  }
319
- async assertQueue(queueName, options) {
352
+ async assertQueue(queueName, connectionRole, options) {
320
353
  RabbitMq.validateName('queue', queueName);
321
354
  if (this.queues[queueName]) {
322
355
  delete this.queueSetupPromises[queueName];
@@ -325,7 +358,7 @@ class RabbitMq {
325
358
  if (this.queueSetupPromises[queueName]) {
326
359
  return this.queueSetupPromises[queueName];
327
360
  }
328
- this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
361
+ this.queueSetupPromises[queueName] = this.setupQueue(queueName, connectionRole, options);
329
362
  return this.queueSetupPromises[queueName];
330
363
  }
331
364
  saveConsumer(queue, callback, options) {
@@ -368,7 +401,7 @@ class RabbitMq {
368
401
  }
369
402
  logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
370
403
  }
371
- const channel = await this.getNewChannel({});
404
+ const channel = await this.getNewChannel({ connectionRole: types_1.ConnectionRole.Consumer });
372
405
  return channel.addSetup(async (confirmChannel) => {
373
406
  await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
374
407
  await confirmChannel.prefetch(limit, true);
@@ -448,7 +481,7 @@ class RabbitMq {
448
481
  RabbitMq.validateName('queue', queue);
449
482
  const { limit, deadMessageTtl } = optionsWithDefaults;
450
483
  await this.saveConsumer(queue, callback, options);
451
- const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
484
+ const channel = await this.getNewChannel({ name: `consume - exchange - ${exchange} -queue - ${queue}`, connectionRole: types_1.ConnectionRole.Consumer });
452
485
  return channel.addSetup(async (c) => {
453
486
  const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
454
487
  await c.assertQueue(queue);
@@ -463,33 +496,44 @@ class RabbitMq {
463
496
  async publish(exchange, content, customHeaders) {
464
497
  return (0, utils_1.wrapSetImmediate)(async () => {
465
498
  RabbitMq.validateName('exchange', exchange);
466
- const channel = await this.assertChannel();
467
- await this.assertExchange(exchange);
499
+ const channel = await this.assertChannel({ connectionRole: types_1.ConnectionRole.Publisher });
500
+ await this.assertExchange(exchange, { connectionRole: types_1.ConnectionRole.Publisher });
468
501
  await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
469
502
  });
470
503
  }
471
- async sendToQueue(queue, content, options, customHeaders, isBlocking) {
472
- const callback = async () => {
473
- try {
474
- RabbitMq.validateName('queue', queue);
475
- await this.assertChannel();
476
- await this.assertQueue(queue, options);
477
- const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
478
- debug(`rabbit: sending to queue ${queue}`, { res });
479
- return res;
480
- }
481
- catch (e) {
482
- logger_1.default.error(`rabbit: failed to send to queue ${queue}`, { e });
483
- throw e;
484
- }
485
- };
486
- if (isBlocking) {
487
- return callback();
504
+ async sendToQueue(queue, content, options, customHeaders) {
505
+ try {
506
+ await this.assertChannel({ connectionRole: types_1.ConnectionRole.Publisher });
507
+ }
508
+ catch (e) {
509
+ logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
510
+ throw e;
511
+ }
512
+ try {
513
+ RabbitMq.validateName('queue', queue);
514
+ await this.assertQueue(queue, types_1.ConnectionRole.Publisher, options);
515
+ }
516
+ catch (e) {
517
+ logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
518
+ throw e;
519
+ }
520
+ try {
521
+ const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
522
+ debug(`rabbit: sending to queue ${queue}`, { res });
523
+ return res;
524
+ }
525
+ catch (e) {
526
+ const isConnected = await this.isConnected(types_1.ConnectionRole.Publisher);
527
+ logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
528
+ throw e;
488
529
  }
489
- return (0, utils_1.wrapSetImmediate)(callback);
490
530
  }
491
- async isConnected() {
492
- const connection = await this.getConnection();
531
+ async isConnected(connectionRole) {
532
+ const connection = await this.getConnection(connectionRole);
533
+ if (!connection) {
534
+ logger_1.default.error('rabbit: isConnected - false');
535
+ return false;
536
+ }
493
537
  const isConnected = connection.isConnected();
494
538
  if (!isConnected) {
495
539
  logger_1.default.error('rabbit: isConnected - false');
@@ -38,3 +38,7 @@ export type AfConsumer = {
38
38
  options: ConsumeOptions | undefined;
39
39
  };
40
40
  export declare const CONSUMER_DEFAULT_OPTIONS: Options.Consume;
41
+ export declare enum ConnectionRole {
42
+ Consumer = "consumer",
43
+ Publisher = "publisher"
44
+ }
package/dist/lib/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CONSUMER_DEFAULT_OPTIONS = void 0;
3
+ exports.ConnectionRole = exports.CONSUMER_DEFAULT_OPTIONS = void 0;
4
4
  const HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';
5
5
  const HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';
6
6
  exports.CONSUMER_DEFAULT_OPTIONS = {
@@ -9,3 +9,8 @@ exports.CONSUMER_DEFAULT_OPTIONS = {
9
9
  [HA_PROMOTE_ON_SHUTDOWN]: 'always',
10
10
  },
11
11
  };
12
+ var ConnectionRole;
13
+ (function (ConnectionRole) {
14
+ ConnectionRole["Consumer"] = "consumer";
15
+ ConnectionRole["Publisher"] = "publisher";
16
+ })(ConnectionRole = exports.ConnectionRole || (exports.ConnectionRole = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.2.19-beta.6",
3
+ "version": "3.2.19-beta.8",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -283,8 +283,8 @@ class RabbitMq implements IAfRabbitMq {
283
283
  : { connectionByRole: this.publishConnection, creatingConnectionByRole: this.creatingPublishConnection });
284
284
 
285
285
  async getConnection(connectionRole: ConnectionRole) {
286
- return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
287
- let { connectionByRole, creatingConnectionByRole } = this.geConnectionByRole(connectionRole);
286
+ return new Promise<AmqpConnectionManager | undefined | null>(async (resolve, reject) => {
287
+ const { connectionByRole, creatingConnectionByRole } = this.geConnectionByRole(connectionRole);
288
288
  if (this.blockReconnect) {
289
289
  debug('rabbit: block reconnect');
290
290
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -296,7 +296,7 @@ class RabbitMq implements IAfRabbitMq {
296
296
  debug('rabbit: connection - is connected');
297
297
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
298
298
  // @ts-ignore
299
- return resolve(this.connection);
299
+ return resolve(connectionByRole);
300
300
  }
301
301
  debug('rabbit: connection - reconnecting');
302
302
  }
@@ -306,7 +306,12 @@ class RabbitMq implements IAfRabbitMq {
306
306
  this.em.once(CONNECTION_FAILED_CONST, reject);
307
307
  return;
308
308
  }
309
- creatingConnectionByRole = true;
309
+ if (connectionRole === ConnectionRole.Consumer) {
310
+ this.creatingConsumeConnection = true;
311
+ } else {
312
+ this.creatingPublishConnection = true;
313
+ }
314
+
310
315
  let isResolved = false;
311
316
 
312
317
  // It is import to use it as a function and not as a variable
@@ -327,8 +332,18 @@ class RabbitMq implements IAfRabbitMq {
327
332
  findServers,
328
333
  });
329
334
 
330
- connectionByRole = newConnection;
331
- connectionByRole.on('error', (err) => {
335
+ if (!newConnection) {
336
+ logger.error('rabbit: couldnt create a connection');
337
+ return resolve(connectionByRole);
338
+ }
339
+
340
+ if (connectionRole === ConnectionRole.Consumer) {
341
+ this.consumeConnection = newConnection;
342
+ } else {
343
+ this.publishConnection = newConnection;
344
+ }
345
+
346
+ newConnection.on('error', (err) => {
332
347
  logger.error('rabbit: connection error', { err });
333
348
  if (!isResolved) {
334
349
  isResolved = true;
@@ -337,7 +352,7 @@ class RabbitMq implements IAfRabbitMq {
337
352
  }
338
353
  });
339
354
 
340
- connectionByRole.on('connectFailed', (err) => {
355
+ newConnection.on('connectFailed', (err) => {
341
356
  this.consumersTags = [];
342
357
  logger.error('rabbit: connection connectFailed', { err });
343
358
  if (!isResolved) {
@@ -347,7 +362,7 @@ class RabbitMq implements IAfRabbitMq {
347
362
  }
348
363
  });
349
364
 
350
- connectionByRole.on('disconnect', ({ err }) => {
365
+ newConnection.on('disconnect', ({ err }) => {
351
366
  this.consumersTags = [];
352
367
  debug('rabbit: connection closed');
353
368
  if (this.options?.disableReconnect) {
@@ -357,12 +372,16 @@ class RabbitMq implements IAfRabbitMq {
357
372
  logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
358
373
  }
359
374
  });
360
- connectionByRole.once('connect', async () => {
375
+ newConnection.once('connect', async () => {
361
376
  debug('rabbit: connection established');
362
- creatingConnectionByRole = false;
363
- this.em.emit(CONNECTION_CREATED_CONST, connectionByRole);
377
+ if (connectionRole === ConnectionRole.Consumer) {
378
+ this.creatingConsumeConnection = false;
379
+ } else {
380
+ this.creatingPublishConnection = false;
381
+ }
382
+ this.em.emit(CONNECTION_CREATED_CONST, newConnection);
364
383
  isResolved = true;
365
- resolve(connectionByRole);
384
+ resolve(newConnection);
366
385
  });
367
386
  });
368
387
  }
@@ -370,13 +389,16 @@ class RabbitMq implements IAfRabbitMq {
370
389
  async getNewChannel({
371
390
  name = rand().toString(), onClose = null, options = {}, connectionRole,
372
391
  }: newChannelOpts = { connectionRole: ConnectionRole.Consumer }): Promise<ChannelWrapper> {
373
- let connection!: AmqpConnectionManager;
392
+ let connection!: AmqpConnectionManager | undefined | null;
374
393
  try {
375
394
  connection = await this.getConnection(connectionRole);
376
395
  } catch (e) {
377
396
  logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
378
397
  throw e;
379
398
  }
399
+ if (!connection) {
400
+ throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
401
+ }
380
402
  const channel = connection.createChannel({ ...options });
381
403
  once(channel, 'close').then((args) => {
382
404
  logger.error(`rabbit: channel ${name} closed`);
@@ -424,7 +446,7 @@ class RabbitMq implements IAfRabbitMq {
424
446
  return exchange;
425
447
  }
426
448
 
427
- async getQueueLength(queue: string, connectionRole: ConnectionRole) {
449
+ async getQueueLength(queue: string, connectionRole: ConnectionRole = ConnectionRole.Consumer): Promise<Replies.AssertQueue> {
428
450
  RabbitMq.validateName('queue', queue);
429
451
  const { connectionByRole } = this.geConnectionByRole(connectionRole);
430
452
  const { channel } = this;
@@ -700,6 +722,10 @@ class RabbitMq implements IAfRabbitMq {
700
722
 
701
723
  async isConnected(connectionRole: ConnectionRole): Promise<boolean> {
702
724
  const connection = await this.getConnection(connectionRole);
725
+ if (!connection) {
726
+ logger.error('rabbit: isConnected - false');
727
+ return false;
728
+ }
703
729
  const isConnected = connection.isConnected();
704
730
  if (!isConnected) {
705
731
  logger.error('rabbit: isConnected - false');
package/src/lib/types.ts CHANGED
@@ -56,4 +56,7 @@ export const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {
56
56
  },
57
57
  };
58
58
 
59
- export type ConnectionRole = 'consumer' | 'publisher';
59
+ export enum ConnectionRole {
60
+ Consumer = 'consumer',
61
+ Publisher = 'publisher',
62
+ }