@autofleet/rabbit 3.2.26-beta.4 → 3.3.0-beta.0

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/src/index.ts CHANGED
@@ -19,8 +19,8 @@ import RabbitError from './lib/rabbitError';
19
19
  import getRedisInstance, { RedisConfig } from './lib/redis';
20
20
  import { assertExchangeFanout, rand, wrapSetImmediate } from './lib/utils';
21
21
  import {
22
- AUTOMATION_ID_HEADER,
23
- ConnectionPurpose,
22
+ CONNECTION_CREATED_CONST,
23
+ CONNECTION_FAILED_CONST,
24
24
  DEFAULT_LOCK_TIMEOUT,
25
25
  DEFAULT_OPTIONS,
26
26
  RETRY_HEADER,
@@ -35,17 +35,14 @@ import {
35
35
  CustomMessageHeaders,
36
36
  QueuesCache,
37
37
  RedisLockType,
38
- ExchangesCache,
39
- CONSUMER_DEFAULT_OPTIONS,
40
- QueueSetupPromisesDictionary,
41
- AssertExchangePromisesDictionary,
42
- ConnectionData,
38
+ ExchangesCache, CONSUMER_DEFAULT_OPTIONS, QueueSetupPromisesDictionary,
43
39
  } from './lib/types';
44
40
 
45
41
  // const debug = nodeDebug('af-rabbitmq')
46
42
  const debug = logger.debug.bind(logger);
47
43
 
48
44
  const PUBLISH_TIMEOUT = 1000 * 10;
45
+
49
46
  export interface IAfRabbitMq {
50
47
  ack: any;
51
48
  nack: any;
@@ -79,19 +76,21 @@ export interface AfRabbitOptions {
79
76
  dontRetryAssert?: boolean;
80
77
 
81
78
  rabbitHost?: string;
79
+
80
+ serviceName: string;
81
+
82
+ podIp?: string;
82
83
  }
83
84
 
84
85
  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
 
@@ -144,27 +143,24 @@ class RabbitMq implements IAfRabbitMq {
144
143
 
145
144
  RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
146
145
 
147
- publishChannel: ChannelWrapper | null;
148
-
149
- publishChannelSetupPromise: Promise<ChannelWrapper> | null;
146
+ channel: ChannelWrapper | null;
150
147
 
151
- blockReconnect: boolean | null | undefined;
148
+ blockReconnect: boolean | null | undefined
152
149
 
153
- connectionsMap: {
154
- [ConnectionPurpose.Consume]: ConnectionData;
155
- [ConnectionPurpose.Publish]: ConnectionData;
156
- };
150
+ connection: AmqpConnectionManager | null | undefined
157
151
 
158
152
  em: EventEmitter;
159
153
 
154
+ podId: string;
155
+
156
+ creatingConnection: boolean;
157
+
160
158
  exchanges: ExchangesCache;
161
159
 
162
160
  queues: QueuesCache;
163
161
 
164
162
  queueSetupPromises: QueueSetupPromisesDictionary;
165
163
 
166
- assertExchangePromises: AssertExchangePromisesDictionary;
167
-
168
164
  options: AfRabbitOptions | undefined;
169
165
 
170
166
  redisClient: any;
@@ -178,28 +174,15 @@ class RabbitMq implements IAfRabbitMq {
178
174
 
179
175
  constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig) {
180
176
  this.em = new EventEmitter();
181
- this.publishChannel = null;
182
- this.publishChannelSetupPromise = null;
183
- this.connectionsMap = {
184
- [ConnectionPurpose.Consume]: {
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
- };
177
+ this.channel = null;
178
+ this.connection = null;
179
+ this.creatingConnection = false;
197
180
  this.exchanges = {};
198
181
  this.queues = {};
199
182
  this.queueSetupPromises = {};
200
- this.assertExchangePromises = {};
201
183
  this.consumers = [];
202
184
  this.options = options;
185
+ this.podId = `${options?.serviceName}${options?.podIp ? `-${options.podIp}` : ''}`;
203
186
  this.redisClient = redisConfig && getRedisInstance(redisConfig);
204
187
  if (this.redisClient) {
205
188
  this.redisLock = promisify(RedisLock(this.redisClient)) as RedisLockType;
@@ -230,7 +213,7 @@ class RabbitMq implements IAfRabbitMq {
230
213
  return false;
231
214
  }
232
215
 
233
- public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage): Promise<any> => {
216
+ public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage) : Promise<any> => {
234
217
  if (msg) {
235
218
  debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });
236
219
  await channel.ack(msg);
@@ -256,8 +239,8 @@ class RabbitMq implements IAfRabbitMq {
256
239
  userMsg: ConsumeMessageOrNull,
257
240
  {
258
241
  skipRetry = false,
259
- }: NackOptions = {},
260
- ): Promise<any> => {
242
+ }: NackOptions = { },
243
+ ) : Promise<any> => {
261
244
  await this.unlockRedisIfNeeded(releaseLock);
262
245
  if (channel && msg) {
263
246
  if (
@@ -291,36 +274,30 @@ class RabbitMq implements IAfRabbitMq {
291
274
  }
292
275
  }
293
276
 
294
- async getConnection(connectionPurpose: ConnectionPurpose) {
295
- return new Promise<AmqpConnectionManager | undefined | null>(async (resolve, reject) => {
296
- const {
297
- connection,
298
- creatingConnection,
299
- connectionCreatedEventName,
300
- connectionFailedEventName,
301
- } = this.connectionsMap[connectionPurpose];
277
+ async getConnection() {
278
+ return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
302
279
  if (this.blockReconnect) {
303
280
  debug('rabbit: block reconnect');
304
281
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
305
282
  // @ts-ignore
306
283
  return resolve();
307
284
  }
308
- if (connection !== null) {
309
- if (this.options?.disableReconnect || connection?.isConnected()) {
285
+ if (this.connection !== null) {
286
+ if (this.options?.disableReconnect || this.connection?.isConnected()) {
310
287
  debug('rabbit: connection - is connected');
311
288
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
312
289
  // @ts-ignore
313
- return resolve(connection);
290
+ return resolve(this.connection);
314
291
  }
315
292
  debug('rabbit: connection - reconnecting');
316
293
  }
317
- if (creatingConnection) {
294
+ if (this.creatingConnection) {
318
295
  debug('rabbit: creating connection emi');
319
- this.em.once(connectionCreatedEventName, resolve);
320
- this.em.once(connectionFailedEventName, reject);
296
+ this.em.once(CONNECTION_CREATED_CONST, resolve);
297
+ this.em.once(CONNECTION_FAILED_CONST, reject);
321
298
  return;
322
299
  }
323
- this.connectionsMap[connectionPurpose].creatingConnection = true;
300
+ this.creatingConnection = true;
324
301
  let isResolved = false;
325
302
 
326
303
  // It is import to use it as a function and not as a variable
@@ -337,33 +314,31 @@ class RabbitMq implements IAfRabbitMq {
337
314
  };
338
315
 
339
316
  const defaultUrls = findServers();
340
- const newConnection: AmqpConnectionManager = await connect(defaultUrls, {
317
+ const connection: AmqpConnectionManager = await connect(defaultUrls, {
341
318
  findServers,
342
319
  });
343
320
 
344
- this.connectionsMap[connectionPurpose].connection = newConnection;
345
- logger.info(`rabbit: created new connection ${connectionPurpose}`);
346
-
347
- newConnection.on('error', (err) => {
321
+ this.connection = connection;
322
+ this.connection.on('error', (err) => {
348
323
  logger.error('rabbit: connection error', { err });
349
324
  if (!isResolved) {
350
325
  isResolved = true;
351
326
  reject(err);
352
- this.em.emit(connectionFailedEventName, err);
327
+ this.em.emit(CONNECTION_FAILED_CONST, err);
353
328
  }
354
329
  });
355
330
 
356
- newConnection.on('connectFailed', (err) => {
331
+ this.connection.on('connectFailed', (err) => {
357
332
  this.consumersTags = [];
358
333
  logger.error('rabbit: connection connectFailed', { err });
359
334
  if (!isResolved) {
360
335
  isResolved = true;
361
336
  reject(err);
362
- this.em.emit(connectionFailedEventName, err);
337
+ this.em.emit(CONNECTION_FAILED_CONST, err);
363
338
  }
364
339
  });
365
340
 
366
- newConnection.on('disconnect', ({ err }) => {
341
+ this.connection.on('disconnect', ({ err }) => {
367
342
  this.consumersTags = [];
368
343
  debug('rabbit: connection closed');
369
344
  if (this.options?.disableReconnect) {
@@ -373,29 +348,25 @@ class RabbitMq implements IAfRabbitMq {
373
348
  logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
374
349
  }
375
350
  });
376
- newConnection.once('connect', async () => {
377
- this.connectionsMap[connectionPurpose].creatingConnection = false;
378
- this.em.emit(connectionCreatedEventName, newConnection);
351
+ this.connection.once('connect', async () => {
352
+ debug('rabbit: connection established');
353
+ this.creatingConnection = false;
354
+ this.em.emit(CONNECTION_CREATED_CONST, connection);
379
355
  isResolved = true;
380
- resolve(newConnection);
356
+ resolve(connection);
381
357
  });
382
358
  });
383
359
  }
384
360
 
385
- async getNewChannel({
386
- name = rand().toString(), onClose = null, options = {}, connectionPurpose = ConnectionPurpose.Consume,
387
- }: newChannelOpts): Promise<ChannelWrapper> {
388
- let connection!: AmqpConnectionManager | undefined | null;
361
+ async getNewChannel({ name = rand().toString(), onClose = null, options = {} }: newChannelOpts = {}) {
362
+ let connection!: AmqpConnectionManager;
389
363
  try {
390
- connection = await this.getConnection(connectionPurpose);
364
+ connection = await this.getConnection();
391
365
  } catch (e) {
392
366
  logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
393
367
  throw e;
394
368
  }
395
- if (!connection) {
396
- throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
397
- }
398
- const channel = connection.createChannel({ ...options });
369
+ const channel = connection.createChannel({ ...options, name });
399
370
  once(channel, 'close').then((args) => {
400
371
  logger.error(`rabbit: channel ${name} closed`);
401
372
  onClose?.(args);
@@ -410,62 +381,48 @@ class RabbitMq implements IAfRabbitMq {
410
381
  }
411
382
  }
412
383
 
413
- async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume }: assertChannelOpts): Promise<ChannelWrapper> {
414
- debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
415
- if (!this.publishChannelSetupPromise) {
416
- this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
417
- if (this.publishChannel && !force) {
418
- return resolve(this.publishChannel);
419
- }
384
+ async assertChannel({ force = false } : assertChannelOpts = {}): Promise<ChannelWrapper> {
385
+ return new Promise<ChannelWrapper>(async (resolve, reject) => {
386
+ if (this.channel && !force) {
387
+ return resolve(this.channel);
388
+ }
420
389
 
421
- try {
422
- const channel = await this.getNewChannel({ connectionPurpose });
423
- debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
424
- channel.on('error', (err) => {
425
- logger.error('rabbit: channel error', { err });
426
- });
427
- if (connectionPurpose === ConnectionPurpose.Publish) {
428
- this.publishChannel = channel;
429
- }
430
- resolve(channel);
431
- } catch (e) {
432
- reject(e);
433
- }
434
- });
435
- }
436
- return this.publishChannelSetupPromise;
390
+ try {
391
+ const channel = await this.getNewChannel({});
392
+ channel.on('error', (err) => {
393
+ logger.error('rabbit: channel error', { err });
394
+ });
395
+ this.channel = channel;
396
+ resolve(channel);
397
+ } catch (e) {
398
+ reject(e);
399
+ }
400
+ });
437
401
  }
438
402
 
439
- async assertExchange(exchangeName: string, options: any = { connectionPurpose: ConnectionPurpose.Consume }) {
440
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: options.connectionPurpose });
403
+ async assertExchange(exchangeName: string, options?: any) {
404
+ const channel: ChannelWrapper = await this.assertChannel();
441
405
  if (this.exchanges[exchangeName]) {
442
- delete this.assertExchangePromises[exchangeName];
443
406
  return this.exchanges[exchangeName];
444
407
  }
445
-
446
- if (this.assertExchangePromises[exchangeName]) {
447
- return this.assertExchangePromises[exchangeName];
448
- }
449
-
450
- this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);
451
- this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];
452
- return this.exchanges[exchangeName];
408
+ const exchange = await assertExchangeFanout(channel, exchangeName);
409
+ this.exchanges[exchangeName] = exchange;
410
+ return exchange;
453
411
  }
454
412
 
455
- async getQueueLength(queue: string, connectionPurpose: ConnectionPurpose = ConnectionPurpose.Consume): Promise<Replies.AssertQueue> {
413
+ async getQueueLength(queue: string) {
456
414
  RabbitMq.validateName('queue', queue);
457
- const { connection } = this.connectionsMap[connectionPurpose];
458
- const { publishChannel } = this;
459
- if (!publishChannel) {
415
+ const { channel } = this;
416
+ if (!channel) {
460
417
  throw new Error('channel is not defined');
461
418
  }
462
- debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
463
- return publishChannel?.checkQueue(queue);
419
+ debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
420
+ return channel?.checkQueue(queue);
464
421
  }
465
422
 
466
- private async deleteQueue(queue: string, connectionPurpose: ConnectionPurpose) {
423
+ private async deleteQueue(queue: string) {
467
424
  RabbitMq.validateName('queue', queue);
468
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose });
425
+ const channel: ChannelWrapper = await this.assertChannel();
469
426
  logger.info('rabbit: deleting queue', { queue });
470
427
  const deleteQueueRes = await channel.deleteQueue(queue);
471
428
  debug('queue deleted', deleteQueueRes);
@@ -473,67 +430,40 @@ class RabbitMq implements IAfRabbitMq {
473
430
  }
474
431
 
475
432
  async bindQueue(queue: string, exchange: string) {
476
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
433
+ const channel: ChannelWrapper = await this.assertChannel();
477
434
  await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));
478
435
  return channel.bindQueue(queue, exchange, '');
479
436
  }
480
437
 
481
438
  async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
482
439
  let queue: Replies.AssertQueue;
483
- const connectionPurpose = ConnectionPurpose.Publish;
484
- const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
485
- const localeOptions = {
486
- ...options,
487
- durable: true,
488
- arguments: {
489
- ...options?.arguments,
490
- 'x-consumer-timeout': 1000 * 60 * 60 * 24,
491
- 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',
492
- },
493
- };
494
440
  try {
495
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose });
441
+ const channel: ChannelWrapper = await this.assertChannel();
496
442
  debug('assertQueue->channel.addSetup', { queueName });
497
- await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
443
+ await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
498
444
  debug('assertQueue->channel.assertQueue', { queueName });
499
- queue = await channel.assertQueue(queueName, localeOptions);
445
+ queue = await channel.assertQueue(queueName, options);
500
446
  } catch (e) {
501
447
  logger.error('rabbit: assertQueue error', { queueName, options, error: e });
502
448
  if (!this.options?.dontRetryAssert) {
503
449
  debug('retrying assertQueue', { queueName });
504
- const channel = await this.assertChannel({ force: true, connectionPurpose });
505
- await this.deleteQueue(queueName, connectionPurpose);
450
+ const channel = await this.assertChannel({ force: true });
451
+ await this.deleteQueue(queueName);
506
452
 
507
453
  debug('retrying assertQueue->channel.addSetup', { queueName });
508
- await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
454
+ await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
509
455
  debug('retrying assertQueue->channel.assertQueue', { queueName });
510
- queue = await channel.assertQueue(queueName, localeOptions);
456
+ queue = await channel.assertQueue(queueName, options);
511
457
  } else {
512
458
  throw e;
513
459
  }
514
460
  }
515
461
 
516
- this.queues[queueName] = queue;
462
+ this.queues[queueName] = queueName;
517
463
  return queue;
518
464
  }
519
465
 
520
- static shouldUseQuorum(queueName: string): boolean {
521
- const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;
522
-
523
- if (envQuorumQueuesWhitelist === '*') {
524
- return true;
525
- }
526
-
527
- if (envQuorumQueuesWhitelist) {
528
- const whitelist = envQuorumQueuesWhitelist.split(',');
529
- return whitelist.includes(queueName);
530
- }
531
-
532
- return false;
533
- }
534
-
535
466
  async assertQueue(queueName: string, options?: Options.AssertQueue) {
536
- debug('rabbit: start assert queue', { queueName });
537
467
  RabbitMq.validateName('queue', queueName);
538
468
  if (this.queues[queueName]) {
539
469
  delete this.queueSetupPromises[queueName];
@@ -545,12 +475,11 @@ class RabbitMq implements IAfRabbitMq {
545
475
  }
546
476
 
547
477
  this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
548
- debug('rabbit: done assert queue', { queueName });
549
478
  return this.queueSetupPromises[queueName];
550
479
  }
551
480
 
552
481
  private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined) {
553
- const isConsumerExist: boolean = this.consumers.some((consumer) => consumer.queue === queue);
482
+ const isConsumerExist :boolean = this.consumers.some((consumer) => consumer.queue === queue);
554
483
  if (!isConsumerExist) {
555
484
  logger.info(`rabbit: consumer: ${queue} saved in consumer array`);
556
485
  this.consumers.push({
@@ -599,10 +528,10 @@ class RabbitMq implements IAfRabbitMq {
599
528
  }
600
529
  logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
601
530
  }
602
- const channel = await this.getNewChannel({ connectionPurpose: ConnectionPurpose.Consume });
531
+ const channel = await this.getNewChannel({ name: `${this.podId}_queue_${queue}` });
603
532
  return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
604
- const q = await this.assertQueue(queue, optionsWithDefaults);
605
- await confirmChannel.prefetch(limit, false);
533
+ await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
534
+ await confirmChannel.prefetch(limit, true);
606
535
  const { consumerTag } = await confirmChannel.consume(
607
536
  queue,
608
537
  async (msg: ConsumeMessageOrNull) => {
@@ -612,7 +541,6 @@ class RabbitMq implements IAfRabbitMq {
612
541
 
613
542
  const traceId = msg.properties.headers[TRACING_HEADER];
614
543
  const userId = msg.properties.headers[USER_TRACING_HEADER];
615
- const automationId = msg.properties.headers[AUTOMATION_ID_HEADER];
616
544
  const parsedMessage = RabbitMq.parseMsg(msg);
617
545
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
618
546
  const trace = newTrace(traceTypes.RABBIT);
@@ -638,10 +566,7 @@ class RabbitMq implements IAfRabbitMq {
638
566
  }
639
567
 
640
568
  if (auditContext) {
641
- await auditContext(queue, {
642
- userId,
643
- automationId,
644
- });
569
+ await auditContext(queue);
645
570
  }
646
571
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
647
572
  if (!shouldConsume) {
@@ -689,19 +614,19 @@ class RabbitMq implements IAfRabbitMq {
689
614
  });
690
615
  }
691
616
 
692
- async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
617
+ async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<any> {
693
618
  const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };
694
619
  RabbitMq.validateName('exchange', exchange);
695
620
  RabbitMq.validateName('queue', queue);
696
621
  const { limit, deadMessageTtl } = optionsWithDefaults;
697
622
  await this.saveConsumer(queue, callback, options);
698
- const channel: ChannelWrapper = await this.getNewChannel({ name: `consume - exchange - ${exchange} -queue - ${queue}` });
623
+ const channel: ChannelWrapper = await this.getNewChannel({ name: `${this.podId}_exchange_${exchange}_queue_${queue}` });
699
624
 
700
625
  return channel.addSetup(async (c: ConfirmChannel) => {
701
626
  const assertExchange = await assertExchangeFanout(c, exchange);
702
627
  await c.assertQueue(queue);
703
628
  this.exchanges[exchange] = assertExchange;
704
- await c.prefetch(limit, false);
629
+ await c.prefetch(limit, true);
705
630
  return Promise.all([
706
631
  c.bindQueue(queue, exchange, ''),
707
632
  this.consume(
@@ -713,12 +638,11 @@ class RabbitMq implements IAfRabbitMq {
713
638
  });
714
639
  }
715
640
 
716
- async publish(exchange: string, content: any, customHeaders?: any): Promise<boolean> {
717
- debug('rabbit: start publish msg');
641
+ async publish(exchange: string, content: any, customHeaders?: any) : Promise<boolean> {
718
642
  return wrapSetImmediate(async () => {
719
643
  RabbitMq.validateName('exchange', exchange);
720
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
721
- await this.assertExchange(exchange, { connectionPurpose: ConnectionPurpose.Publish });
644
+ const channel: ChannelWrapper = await this.assertChannel();
645
+ await this.assertExchange(exchange);
722
646
  await channel.publish(exchange, '',
723
647
  Buffer.from(JSON.stringify(content)),
724
648
  RabbitMq.getPublishOptions(customHeaders));
@@ -730,86 +654,51 @@ class RabbitMq implements IAfRabbitMq {
730
654
  content: any,
731
655
  options?: any,
732
656
  customHeaders?: any,
657
+ isBlocking?: boolean,
733
658
  ): Promise<boolean | undefined> {
734
- try {
735
- await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
736
- } catch (e) {
737
- logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
738
- throw e;
659
+ const callback = async (): Promise<boolean | undefined> => {
660
+ try {
661
+ RabbitMq.validateName('queue', queue);
662
+ await this.assertChannel();
663
+ await this.assertQueue(queue, options);
664
+ const res = await this.channel?.sendToQueue(queue,
665
+ Buffer.from(JSON.stringify(content)),
666
+ RabbitMq.getPublishOptions(customHeaders));
667
+ debug(`rabbit: sending to queue ${queue}`, { res });
668
+ return res;
669
+ } catch (e) {
670
+ logger.error(`rabbit: failed to send to queue ${queue}`, { e });
671
+ throw e;
672
+ }
673
+ };
674
+ if (isBlocking) {
675
+ return callback();
739
676
  }
677
+ return wrapSetImmediate(callback);
678
+ }
740
679
 
741
- try {
742
- RabbitMq.validateName('queue', queue);
743
- await this.assertQueue(queue, options);
744
- } catch (e) {
745
- logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
746
- throw e;
680
+ async isConnected() : Promise<boolean> {
681
+ const connection = await this.getConnection();
682
+ const isConnected = connection.isConnected();
683
+ if (!isConnected) {
684
+ logger.error('rabbit: isConnected - false');
685
+ return false;
747
686
  }
748
-
687
+ const channel: any = await this.assertChannel();
749
688
  try {
750
- const res = await this.publishChannel?.sendToQueue(queue,
751
- Buffer.from(JSON.stringify(content)),
752
- RabbitMq.getPublishOptions(customHeaders));
753
- debug(`rabbit: sending to queue ${queue}`, { res });
754
- return res;
689
+ await Promise.all([
690
+ channel.waitForConnect(),
691
+ ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
692
+ ]);
755
693
  } catch (e) {
756
- logger.error(`rabbit sendToQueue: failed to send to queue ${queue}`, { e });
757
- throw e;
694
+ logger.error('rabbit: isConnected - false');
695
+ return false;
758
696
  }
697
+ logger.info('rabbit: isConnected - true');
698
+ return true;
759
699
  }
760
700
 
761
- // const connection = await this.getConnection();
762
- // const isConnected = connection.isConnected();
763
- // if (!isConnected) {
764
- // logger.error('rabbit: isConnected - false');
765
- // return false;
766
- // }
767
- // const channel: any = await this.assertChannel();
768
- // try {
769
- // await Promise.all([
770
- // channel.waitForConnect(),
771
- // ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
772
- // ]);
773
- // } catch (e) {
774
- // logger.error('rabbit: isConnected - false');
775
- // return false;
776
- // }
777
- // logger.info('rabbit: isConnected - true');
778
- // return true;
779
-
780
- async isConnected(): Promise<boolean> {
781
- debug('rabbit: start is connected');
782
- const isEachConnectionConnected = await Promise.all(
783
- Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
784
- const { connection } = connectionData;
785
- if (connectionPurpose === ConnectionPurpose.Publish && connection) {
786
- const channel: any = await this.assertChannel({ connectionPurpose: connectionPurpose as ConnectionPurpose });
787
- try {
788
- await Promise.all([
789
- channel.waitForConnect(),
790
- ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
791
- ]);
792
- } catch (e) {
793
- logger.error('rabbit: isConnected - false');
794
- return false;
795
- }
796
- }
797
-
798
- if (connection) {
799
- const isConnected = connection?.isConnected();
800
- if (!isConnected) {
801
- logger.error('rabbit: isConnected - false', { connectionPurpose });
802
- return false;
803
- }
804
- logger.info('rabbit: isConnected - true', { connectionPurpose });
805
- }
806
- return true;
807
- }),
808
- );
809
- return isEachConnectionConnected.every((isConnected) => isConnected === true);
810
- }
811
-
812
- async gracefulShutdown(signal: string): Promise<void> {
701
+ async gracefulShutdown(signal: string) : Promise<void> {
813
702
  const tagsNumber = this.consumersTags.length;
814
703
  logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);
815
704
  const cancelTagPromises = this.consumersTags.map(([channel, tag]) => channel.cancel(tag));
@@ -826,7 +715,3 @@ class RabbitMq implements IAfRabbitMq {
826
715
  }
827
716
 
828
717
  export default RabbitMq;
829
-
830
- export {
831
- sendCeleryTaskViaHttp,
832
- } from './lib/celery';
package/src/lib/consts.ts CHANGED
@@ -3,9 +3,10 @@ export const DEFAULT_LOCK_TIMEOUT = 1000 * 5;
3
3
  export const RETRY_HEADER = 'x-retry-count';
4
4
  export const TRACING_HEADER = 'x-trace-id';
5
5
  export const USER_TRACING_HEADER = 'x-af-user-id';
6
- export const AUTOMATION_ID_HEADER = 'x-af-automation-id';
7
6
  export const USER_OBJECT = 'userObject';
8
7
  export const DEFAULT_USE_CONSUME_WITH_LOCK = false;
8
+ export const CONNECTION_CREATED_CONST = 'connectionCreated';
9
+ export const CONNECTION_FAILED_CONST = 'connectionFailed';
9
10
  export const DEFAULT_OPTIONS = {
10
11
  limit: 1,
11
12
  retries: 1,
@@ -15,8 +16,3 @@ export const DEFAULT_OPTIONS = {
15
16
  auditContext: null,
16
17
  enableRabbitTrace: false,
17
18
  };
18
-
19
- export enum ConnectionPurpose {
20
- Consume = 'consume',
21
- Publish = 'publish',
22
- }