@autofleet/rabbit 3.2.26-beta.2 → 3.2.26-beta.201

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
@@ -1,10 +1,10 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
- import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from 'amqp-connection-manager';
3
+ import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
4
4
  import { ConfirmChannel, ConsumeMessage, Options, Replies } from 'amqplib';
5
5
  import { RedisConfig } from './lib/redis';
6
6
  import { ConnectionPurpose } from './lib/consts';
7
- import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData } from './lib/types';
7
+ import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData, assertChannelOpts, newChannelOpts, PublishOptions } from './lib/types';
8
8
  export interface IAfRabbitMq {
9
9
  ack: any;
10
10
  nack: any;
@@ -34,17 +34,6 @@ export interface AfRabbitOptions {
34
34
  dontRetryAssert?: boolean;
35
35
  rabbitHost?: string;
36
36
  }
37
- type newChannelOpts = {
38
- name?: string;
39
- onClose?: null | ((args: any | null) => void);
40
- options?: CreateChannelOpts | undefined;
41
- connectionPurpose?: ConnectionPurpose;
42
- };
43
- type assertChannelOpts = {
44
- channelName?: string;
45
- force?: boolean;
46
- connectionPurpose?: ConnectionPurpose;
47
- };
48
37
  declare class RabbitMq implements IAfRabbitMq {
49
38
  static parseMsg(msg: any): any;
50
39
  static validateName(type: string, name: string): void;
@@ -84,7 +73,7 @@ declare class RabbitMq implements IAfRabbitMq {
84
73
  nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
85
74
  getConnection(connectionPurpose: ConnectionPurpose): Promise<AmqpConnectionManager | null | undefined>;
86
75
  getNewChannel({ name, onClose, options, connectionPurpose, }: newChannelOpts): Promise<ChannelWrapper>;
87
- assertChannel({ force, connectionPurpose }: assertChannelOpts): Promise<ChannelWrapper>;
76
+ assertChannel({ force, connectionPurpose, newChannelOptions }: assertChannelOpts): Promise<ChannelWrapper>;
88
77
  assertExchange(exchangeName: string, options?: any): Promise<any>;
89
78
  getQueueLength(queue: string, connectionPurpose?: ConnectionPurpose): Promise<Replies.AssertQueue>;
90
79
  private deleteQueue;
@@ -98,7 +87,7 @@ declare class RabbitMq implements IAfRabbitMq {
98
87
  private unlockRedisIfNeeded;
99
88
  private consumeFromRabbit;
100
89
  consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
101
- publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
90
+ publish(exchange: string, content: any, customHeaders?: any, options?: PublishOptions): Promise<boolean>;
102
91
  sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean | undefined>;
103
92
  isConnected(): Promise<boolean>;
104
93
  gracefulShutdown(signal: string): Promise<void>;
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.sendCeleryTaskViaHttp = void 0;
8
8
  const events_1 = require("events");
9
9
  const util_1 = require("util");
10
+ const lodash_1 = require("lodash");
10
11
  const moment_1 = __importDefault(require("moment"));
11
12
  const redis_lock_1 = __importDefault(require("redis-lock"));
12
13
  const amqp_connection_manager_1 = require("amqp-connection-manager");
@@ -131,6 +132,7 @@ class RabbitMq {
131
132
  creatingConnection: false,
132
133
  connectionCreatedEventName: 'publishConnectionCreated',
133
134
  connectionFailedEventName: 'publishConnectionFailed',
135
+ doesChannelInitialize: false,
134
136
  },
135
137
  };
136
138
  this.exchanges = {};
@@ -259,7 +261,7 @@ class RabbitMq {
259
261
  throw err;
260
262
  }
261
263
  }
262
- async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume }) {
264
+ async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume, newChannelOptions = {} }) {
263
265
  debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
264
266
  if (!this.publishChannelSetupPromise || (!this.publishChannel && connectionPurpose === consts_1.ConnectionPurpose.Publish)) {
265
267
  this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
@@ -267,13 +269,14 @@ class RabbitMq {
267
269
  return resolve(this.publishChannel);
268
270
  }
269
271
  try {
270
- const channel = await this.getNewChannel({ connectionPurpose });
272
+ const channel = await this.getNewChannel({ connectionPurpose, options: newChannelOptions });
271
273
  debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
272
274
  channel.on('error', (err) => {
273
275
  logger_1.default.error('rabbit: channel error', { err });
274
276
  });
275
277
  if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
276
278
  this.publishChannel = channel;
279
+ this.connectionsMap[connectionPurpose].doesChannelInitialize = true;
277
280
  }
278
281
  resolve(channel);
279
282
  }
@@ -426,6 +429,9 @@ class RabbitMq {
426
429
  return channel.addSetup(async (confirmChannel) => {
427
430
  const q = await this.assertQueue(queue, consts_1.ConnectionPurpose.Consume, optionsWithDefaults);
428
431
  await confirmChannel.prefetch(limit, false);
432
+ const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
433
+ ? (0, lodash_1.merge)(types_1.CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
434
+ : types_1.CONSUMER_DEFAULT_OPTIONS;
429
435
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
430
436
  if (!msg) {
431
437
  return null;
@@ -490,7 +496,7 @@ class RabbitMq {
490
496
  catch (e) {
491
497
  await localNack(msg);
492
498
  }
493
- }, types_1.CONSUMER_DEFAULT_OPTIONS);
499
+ }, channelConsumerOptions);
494
500
  if (!consumerTag) {
495
501
  logger_1.default.error(`rabbit: failed to consume from queue ${queue}`);
496
502
  }
@@ -518,18 +524,24 @@ class RabbitMq {
518
524
  ]);
519
525
  });
520
526
  }
521
- async publish(exchange, content, customHeaders) {
527
+ async publish(exchange, content, customHeaders, options) {
522
528
  debug('rabbit: start publish msg');
523
529
  return (0, utils_1.wrapSetImmediate)(async () => {
524
530
  RabbitMq.validateName('exchange', exchange);
525
- const channel = await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
531
+ const channel = await this.assertChannel({
532
+ connectionPurpose: consts_1.ConnectionPurpose.Publish,
533
+ newChannelOptions: options?.newChannelOptions,
534
+ });
526
535
  await this.assertExchange(exchange, { connectionPurpose: consts_1.ConnectionPurpose.Publish });
527
536
  await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
528
537
  });
529
538
  }
530
539
  async sendToQueue(queue, content, options, customHeaders) {
531
540
  try {
532
- await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
541
+ await this.assertChannel({
542
+ connectionPurpose: consts_1.ConnectionPurpose.Publish,
543
+ newChannelOptions: options?.newChannelOptions,
544
+ });
533
545
  }
534
546
  catch (e) {
535
547
  logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
@@ -556,14 +568,16 @@ class RabbitMq {
556
568
  async isConnected() {
557
569
  debug('rabbit: start is connected');
558
570
  const isEachConnectionConnected = await Promise.all(Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
559
- const { connection } = connectionData;
560
- debug('rabbit: is connected inside map', { connection, connectionPurpose });
561
- const isConnected = connection?.isConnected();
562
- if (!isConnected) {
563
- logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
564
- return false;
565
- }
566
- if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
571
+ const { connection, doesChannelInitialize } = connectionData;
572
+ if (connectionPurpose === consts_1.ConnectionPurpose.Consume
573
+ || (connectionPurpose === consts_1.ConnectionPurpose.Publish
574
+ && doesChannelInitialize)) {
575
+ debug('rabbit: is connected inside map', { connection, connectionPurpose });
576
+ const isConnected = connection?.isConnected();
577
+ if (!isConnected) {
578
+ logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
579
+ return false;
580
+ }
567
581
  const channel = await this.assertChannel({ connectionPurpose: connectionPurpose });
568
582
  try {
569
583
  await Promise.all([
@@ -1,5 +1,6 @@
1
- import { AmqpConnectionManager } from 'amqp-connection-manager';
1
+ import { AmqpConnectionManager, CreateChannelOpts } from 'amqp-connection-manager';
2
2
  import { ConsumeMessage, Options, Replies } from 'amqplib';
3
+ import { ConnectionPurpose } from './consts';
3
4
  export interface ExchangesCache {
4
5
  [key: string]: any;
5
6
  }
@@ -26,25 +27,34 @@ export interface ConsumeOptions {
26
27
  useConsumeWithLock?: boolean;
27
28
  auditContext?: any;
28
29
  enableRabbitTrace?: boolean;
30
+ channelConsumeOptions?: Options.Consume;
29
31
  }
30
32
  export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>;
31
33
  export type newChannelOpts = {
32
34
  name?: string;
33
35
  onClose?: null | ((args: any | null) => void);
36
+ options?: CreateChannelOpts | undefined;
37
+ connectionPurpose?: ConnectionPurpose;
34
38
  };
35
39
  export type assertChannelOpts = {
36
40
  channelName?: string;
37
41
  force?: boolean;
42
+ newChannelOptions?: newChannelOpts;
43
+ connectionPurpose?: ConnectionPurpose;
38
44
  };
39
45
  export type AfConsumer = {
40
46
  queue: string;
41
47
  callback: CallbackFunction;
42
48
  options: ConsumeOptions | undefined;
43
49
  };
50
+ export interface PublishOptions {
51
+ newChannelOptions?: newChannelOpts;
52
+ }
44
53
  export declare const CONSUMER_DEFAULT_OPTIONS: Options.Consume;
45
54
  export type ConnectionData = {
46
55
  connection: AmqpConnectionManager | null;
47
56
  creatingConnection: boolean;
48
57
  connectionCreatedEventName: string;
49
58
  connectionFailedEventName: string;
59
+ doesChannelInitialize?: boolean;
50
60
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.2.26-beta.2",
3
+ "version": "3.2.26-beta.201",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "engines": {
@@ -19,9 +19,11 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@autofleet/zehut": "^3.1.2",
22
+ "@types/lodash": "^4.17.16",
22
23
  "amqp-connection-manager": "4.1.9",
23
24
  "amqplib": "0.10.3",
24
25
  "bluebird": "^3.7.2",
26
+ "lodash": "^4.17.21",
25
27
  "moment": "^2.29.1",
26
28
  "redis": "^3.1.2",
27
29
  "redis-lock": "^0.1.4"
package/src/index.ts CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  import { EventEmitter, once } from 'events';
4
4
  import { promisify } from 'util';
5
+ import { merge } from 'lodash';
5
6
  import moment from 'moment';
6
7
  import RedisLock from 'redis-lock';
7
8
  import {
8
- AmqpConnectionManager, ChannelWrapper, connect, CreateChannelOpts,
9
+ AmqpConnectionManager, ChannelWrapper, connect,
9
10
  } from 'amqp-connection-manager';
10
11
  import {
11
12
  ConfirmChannel, ConsumeMessage, Options, Replies,
@@ -40,6 +41,9 @@ import {
40
41
  QueueSetupPromisesDictionary,
41
42
  AssertExchangePromisesDictionary,
42
43
  ConnectionData,
44
+ assertChannelOpts,
45
+ newChannelOpts,
46
+ PublishOptions,
43
47
  } from './lib/types';
44
48
 
45
49
  // const debug = nodeDebug('af-rabbitmq')
@@ -81,19 +85,6 @@ export interface AfRabbitOptions {
81
85
  rabbitHost?: string;
82
86
  }
83
87
 
84
- type newChannelOpts = {
85
- name?: string;
86
- onClose?: null | ((args: any | null) => void);
87
- options?: CreateChannelOpts | undefined;
88
- connectionPurpose?: ConnectionPurpose,
89
- };
90
-
91
- type assertChannelOpts = {
92
- channelName?: string;
93
- force?: boolean;
94
- connectionPurpose?: ConnectionPurpose;
95
- }
96
-
97
88
  type AfConsumer = {
98
89
  queue: string;
99
90
  callback: CallbackFunction;
@@ -192,6 +183,7 @@ class RabbitMq implements IAfRabbitMq {
192
183
  creatingConnection: false,
193
184
  connectionCreatedEventName: 'publishConnectionCreated',
194
185
  connectionFailedEventName: 'publishConnectionFailed',
186
+ doesChannelInitialize: false,
195
187
  },
196
188
  };
197
189
  this.exchanges = {};
@@ -410,7 +402,7 @@ class RabbitMq implements IAfRabbitMq {
410
402
  }
411
403
  }
412
404
 
413
- async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume }: assertChannelOpts): Promise<ChannelWrapper> {
405
+ async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume, newChannelOptions = {} }: assertChannelOpts): Promise<ChannelWrapper> {
414
406
  debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
415
407
  if (!this.publishChannelSetupPromise || (!this.publishChannel && connectionPurpose === ConnectionPurpose.Publish)) {
416
408
  this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
@@ -419,13 +411,14 @@ class RabbitMq implements IAfRabbitMq {
419
411
  }
420
412
 
421
413
  try {
422
- const channel = await this.getNewChannel({ connectionPurpose });
414
+ const channel = await this.getNewChannel({ connectionPurpose, options: newChannelOptions });
423
415
  debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
424
416
  channel.on('error', (err) => {
425
417
  logger.error('rabbit: channel error', { err });
426
418
  });
427
419
  if (connectionPurpose === ConnectionPurpose.Publish) {
428
420
  this.publishChannel = channel;
421
+ this.connectionsMap[connectionPurpose].doesChannelInitialize = true;
429
422
  }
430
423
  resolve(channel);
431
424
  } catch (e) {
@@ -602,6 +595,9 @@ class RabbitMq implements IAfRabbitMq {
602
595
  return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
603
596
  const q = await this.assertQueue(queue, ConnectionPurpose.Consume, optionsWithDefaults);
604
597
  await confirmChannel.prefetch(limit, false);
598
+ const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
599
+ ? merge(CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
600
+ : CONSUMER_DEFAULT_OPTIONS;
605
601
  const { consumerTag } = await confirmChannel.consume(
606
602
  queue,
607
603
  async (msg: ConsumeMessageOrNull) => {
@@ -677,7 +673,7 @@ class RabbitMq implements IAfRabbitMq {
677
673
  } catch (e) {
678
674
  await localNack(msg);
679
675
  }
680
- }, CONSUMER_DEFAULT_OPTIONS,
676
+ }, channelConsumerOptions,
681
677
  );
682
678
  if (!consumerTag) {
683
679
  logger.error(`rabbit: failed to consume from queue ${queue}`);
@@ -712,11 +708,14 @@ class RabbitMq implements IAfRabbitMq {
712
708
  });
713
709
  }
714
710
 
715
- async publish(exchange: string, content: any, customHeaders?: any): Promise<boolean> {
711
+ async publish(exchange: string, content: any, customHeaders?: any, options?: PublishOptions): Promise<boolean> {
716
712
  debug('rabbit: start publish msg');
717
713
  return wrapSetImmediate(async () => {
718
714
  RabbitMq.validateName('exchange', exchange);
719
- const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
715
+ const channel: ChannelWrapper = await this.assertChannel({
716
+ connectionPurpose: ConnectionPurpose.Publish,
717
+ newChannelOptions: options?.newChannelOptions,
718
+ });
720
719
  await this.assertExchange(exchange, { connectionPurpose: ConnectionPurpose.Publish });
721
720
  await channel.publish(exchange, '',
722
721
  Buffer.from(JSON.stringify(content)),
@@ -731,7 +730,10 @@ class RabbitMq implements IAfRabbitMq {
731
730
  customHeaders?: any,
732
731
  ): Promise<boolean | undefined> {
733
732
  try {
734
- await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
733
+ await this.assertChannel({
734
+ connectionPurpose: ConnectionPurpose.Publish,
735
+ newChannelOptions: options?.newChannelOptions,
736
+ });
735
737
  } catch (e) {
736
738
  logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
737
739
  throw e;
@@ -761,14 +763,18 @@ class RabbitMq implements IAfRabbitMq {
761
763
  debug('rabbit: start is connected');
762
764
  const isEachConnectionConnected = await Promise.all(
763
765
  Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
764
- const { connection } = connectionData;
765
- debug('rabbit: is connected inside map', { connection, connectionPurpose });
766
- const isConnected = connection?.isConnected();
767
- if (!isConnected) {
768
- logger.error('rabbit: isConnected - false', { connectionPurpose });
769
- return false;
770
- }
771
- if (connectionPurpose === ConnectionPurpose.Publish) {
766
+ const { connection, doesChannelInitialize } = connectionData;
767
+ if (
768
+ connectionPurpose === ConnectionPurpose.Consume
769
+ || (connectionPurpose === ConnectionPurpose.Publish
770
+ && doesChannelInitialize
771
+ )) {
772
+ debug('rabbit: is connected inside map', { connection, connectionPurpose });
773
+ const isConnected = connection?.isConnected();
774
+ if (!isConnected) {
775
+ logger.error('rabbit: isConnected - false', { connectionPurpose });
776
+ return false;
777
+ }
772
778
  const channel: any = await this.assertChannel({ connectionPurpose: connectionPurpose as ConnectionPurpose });
773
779
  try {
774
780
  await Promise.all([
package/src/lib/types.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { AmqpConnectionManager } from 'amqp-connection-manager';
1
+ import { AmqpConnectionManager, CreateChannelOpts } from 'amqp-connection-manager';
2
2
  import { ConsumeMessage, Options, Replies } from 'amqplib';
3
+ import { ConnectionPurpose } from './consts';
3
4
 
4
5
  export interface ExchangesCache {
5
6
  [key: string]: any
@@ -32,6 +33,7 @@ export interface ConsumeOptions {
32
33
  useConsumeWithLock?: boolean;
33
34
  auditContext?: any;
34
35
  enableRabbitTrace?: boolean;
36
+ channelConsumeOptions?: Options.Consume;
35
37
  }
36
38
 
37
39
  export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>
@@ -39,10 +41,14 @@ export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Pro
39
41
  export type newChannelOpts = {
40
42
  name?: string;
41
43
  onClose?: null | ((args: any | null) => void);
44
+ options?: CreateChannelOpts | undefined;
45
+ connectionPurpose?: ConnectionPurpose;
42
46
  };
43
47
  export type assertChannelOpts = {
44
48
  channelName?: string;
45
49
  force?: boolean;
50
+ newChannelOptions?: newChannelOpts;
51
+ connectionPurpose?: ConnectionPurpose;
46
52
  }
47
53
  export type AfConsumer = {
48
54
  queue: string;
@@ -50,6 +56,10 @@ export type AfConsumer = {
50
56
  options: ConsumeOptions | undefined;
51
57
  }
52
58
 
59
+ export interface PublishOptions {
60
+ newChannelOptions?: newChannelOpts;
61
+ }
62
+
53
63
  const HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';
54
64
 
55
65
  const HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';
@@ -66,4 +76,5 @@ export type ConnectionData = {
66
76
  creatingConnection: boolean;
67
77
  connectionCreatedEventName: string;
68
78
  connectionFailedEventName: string;
79
+ doesChannelInitialize?: boolean;
69
80
  };