@autofleet/rabbit 3.1.2 → 3.2.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/dist/index.d.ts CHANGED
@@ -29,6 +29,7 @@ export interface AfRabbitOptions {
29
29
  * @default false
30
30
  */
31
31
  dontRetryAssert?: boolean;
32
+ rabbitHost?: string;
32
33
  }
33
34
  declare type newChannelOpts = {
34
35
  name?: string;
@@ -43,6 +44,7 @@ declare class RabbitMq implements IAfRabbitMq {
43
44
  static validateName(type: string, name: string): void;
44
45
  static getPublishOptions(customHeaders?: CustomMessageHeaders): {
45
46
  timestamp: number;
47
+ timeout: number;
46
48
  headers: {
47
49
  "x-af-user-id": any;
48
50
  "x-trace-id": any;
@@ -62,6 +64,9 @@ declare class RabbitMq implements IAfRabbitMq {
62
64
  options: AfRabbitOptions | undefined;
63
65
  redisClient: any;
64
66
  redisLock?: RedisLockType;
67
+ userName: string;
68
+ password: string;
69
+ host: string;
65
70
  /** Array of consumers tags used for canceling consumption */
66
71
  consumersTags: Array<[ConfirmChannel, string]>;
67
72
  private consumers;
package/dist/index.js CHANGED
@@ -18,14 +18,10 @@ const consts_1 = require("./lib/consts");
18
18
  const types_1 = require("./lib/types");
19
19
  // const debug = nodeDebug('af-rabbitmq')
20
20
  const debug = logger_1.default.info;
21
- const USERNAME = process.env.RABBITMQ_USERNAME || 'guest';
22
- const PASSWORD = process.env.RABBITMQ_PASSWORD || 'guest';
23
- const HOST = process.env.RABBITMQ_SERVICE_HOST || 'localhost';
21
+ const PUBLISH_TIMEOUT = 1000 * 10;
24
22
  const HEARTBEAT = '60';
25
23
  class RabbitMq {
26
24
  constructor(options, redisConfig) {
27
- // PUBLISH_TIMEOUT = Number(process.env.RABBITMQ_PUBLISH_TIMEOUT) || 60000;
28
- // PUBLISH_ERROR_MSG = `rabbit: publish timeout(${this.PUBLISH_TIMEOUT}ms) has pass, exchange: `;
29
25
  this.DISCONNECT_MSG = 'rabbit: connection disconnect';
30
26
  this.RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
31
27
  this.consumers = [];
@@ -84,6 +80,9 @@ class RabbitMq {
84
80
  });
85
81
  }
86
82
  };
83
+ this.userName = process.env.RABBITMQ_USERNAME || 'guest';
84
+ this.password = process.env.RABBITMQ_PASSWORD || 'guest';
85
+ this.host = options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';
87
86
  this.em = new events_1.EventEmitter();
88
87
  this.channel = null;
89
88
  this.connection = null;
@@ -130,6 +129,7 @@ class RabbitMq {
130
129
  const outbreakTrace = zehut_1.outbreak.getCurrentContext();
131
130
  return {
132
131
  timestamp: moment_1.default().unix(),
132
+ timeout: PUBLISH_TIMEOUT,
133
133
  headers: {
134
134
  creationTimestamp: moment_1.default().valueOf(),
135
135
  ...customHeaders,
@@ -163,8 +163,8 @@ class RabbitMq {
163
163
  }
164
164
  this.creatingConnection = true;
165
165
  let isResolved = false;
166
- debug('rabbit: creating connection', { HOST, USERNAME, HEARTBEAT });
167
- const connection = await amqp_connection_manager_1.connect([`amqp://${USERNAME}:${PASSWORD}@${HOST}?heartbeat=${HEARTBEAT}}`]);
166
+ debug('rabbit: creating connection', { host: this.host, userName: this.userName, HEARTBEAT });
167
+ const connection = await amqp_connection_manager_1.connect([`amqp://${this.userName}:${this.password}@${this.host}?heartbeat=${HEARTBEAT}}`]);
168
168
  this.connection = connection;
169
169
  this.connection.on('error', (err) => {
170
170
  logger_1.default.error('rabbit: connection error', { err });
@@ -186,8 +186,6 @@ class RabbitMq {
186
186
  debug('rabbit: connection closed');
187
187
  this.exchanges = {};
188
188
  this.queues = {};
189
- this.connection = null;
190
- this.channel = null;
191
189
  if (this.options?.disableReconnect) {
192
190
  logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
193
191
  this.blockReconnect = true;
@@ -237,10 +235,9 @@ class RabbitMq {
237
235
  return resolve(this.channel);
238
236
  }
239
237
  try {
240
- const channel = await this.getNewChannel({
241
- onClose: () => {
242
- this.channel = null;
243
- },
238
+ const channel = await this.getNewChannel({});
239
+ channel.on('error', (err) => {
240
+ logger_1.default.error('rabbit: channel error', { err });
244
241
  });
245
242
  this.channel = channel;
246
243
  resolve(channel);
@@ -437,12 +434,18 @@ class RabbitMq {
437
434
  }
438
435
  async sendToQueue(queue, content, options, customHeaders, isBlocking) {
439
436
  const callback = async () => {
440
- RabbitMq.validateName('queue', queue);
441
- await this.assertChannel();
442
- await this.assertQueue(queue, options);
443
- const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
444
- debug(`rabbit: sending to queue ${queue}`, { res });
445
- return res;
437
+ try {
438
+ RabbitMq.validateName('queue', queue);
439
+ await this.assertChannel();
440
+ await this.assertQueue(queue, options);
441
+ const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
442
+ debug(`rabbit: sending to queue ${queue}`, { res });
443
+ return res;
444
+ }
445
+ catch (e) {
446
+ logger_1.default.error(`rabbit: failed to send to queue ${queue}`, { e });
447
+ throw e;
448
+ }
446
449
  };
447
450
  if (isBlocking) {
448
451
  return callback();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.1.2",
3
+ "version": "3.2.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -9,7 +9,7 @@
9
9
  "example": "ts-node src/example.ts",
10
10
  "build": "rm -rf dist && tsc",
11
11
  "linter": "./node_modules/.bin/eslint .",
12
- "test": "jest --forceExit",
12
+ "test": "jest --runInBand --forceExit",
13
13
  "test-local": "RABBITMQ_SERVICE_HOST=localhost:5672 jest --forceExit",
14
14
  "coverage": "jest --coverage --forceExit && rm -rf ./coverage",
15
15
  "dev": "nodemon"
@@ -37,6 +37,7 @@
37
37
  "eslint-config-airbnb-typescript": "^12.0.0",
38
38
  "eslint-plugin-import": "^2.22.1",
39
39
  "jest": "^27.0.5",
40
+ "node-tcp-proxy": "^0.0.28",
40
41
  "ts-jest": "^27.0.3",
41
42
  "ts-node": "^8.6.2",
42
43
  "typescript": "^3.8.3"
package/src/index.ts CHANGED
@@ -38,6 +38,7 @@ import {
38
38
  // const debug = nodeDebug('af-rabbitmq')
39
39
  const debug = logger.info;
40
40
 
41
+ const PUBLISH_TIMEOUT = 1000 * 10;
41
42
  export interface IAfRabbitMq {
42
43
  ack: any;
43
44
  nack: any;
@@ -65,6 +66,8 @@ export interface AfRabbitOptions {
65
66
  * @default false
66
67
  */
67
68
  dontRetryAssert?: boolean;
69
+
70
+ rabbitHost?: string;
68
71
  }
69
72
 
70
73
  type newChannelOpts = {
@@ -83,12 +86,6 @@ type AfConsumer = {
83
86
  options: ConsumeOptions | undefined;
84
87
  }
85
88
 
86
- const USERNAME: string = process.env.RABBITMQ_USERNAME || 'guest';
87
-
88
- const PASSWORD: string = process.env.RABBITMQ_PASSWORD || 'guest';
89
-
90
- const HOST: string = process.env.RABBITMQ_SERVICE_HOST || 'localhost';
91
-
92
89
  const HEARTBEAT = '60';
93
90
 
94
91
  class RabbitMq implements IAfRabbitMq {
@@ -119,6 +116,7 @@ class RabbitMq implements IAfRabbitMq {
119
116
  const outbreakTrace = outbreak.getCurrentContext();
120
117
  return {
121
118
  timestamp: moment().unix(),
119
+ timeout: PUBLISH_TIMEOUT,
122
120
  headers: {
123
121
  creationTimestamp: moment().valueOf(),
124
122
  ...customHeaders,
@@ -128,10 +126,6 @@ class RabbitMq implements IAfRabbitMq {
128
126
  };
129
127
  }
130
128
 
131
- // PUBLISH_TIMEOUT = Number(process.env.RABBITMQ_PUBLISH_TIMEOUT) || 60000;
132
-
133
- // PUBLISH_ERROR_MSG = `rabbit: publish timeout(${this.PUBLISH_TIMEOUT}ms) has pass, exchange: `;
134
-
135
129
  DISCONNECT_MSG = 'rabbit: connection disconnect';
136
130
 
137
131
  RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
@@ -156,12 +150,24 @@ class RabbitMq implements IAfRabbitMq {
156
150
 
157
151
  redisLock?: RedisLockType;
158
152
 
153
+ userName: string;
154
+
155
+ password: string;
156
+
157
+ host: string;
158
+
159
159
  /** Array of consumers tags used for canceling consumption */
160
160
  consumersTags: Array<[ConfirmChannel, string]>;
161
161
 
162
162
  private consumers: Array<AfConsumer> = [];
163
163
 
164
164
  constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig) {
165
+ this.userName = process.env.RABBITMQ_USERNAME || 'guest';
166
+
167
+ this.password = process.env.RABBITMQ_PASSWORD || 'guest';
168
+
169
+ this.host = options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';
170
+
165
171
  this.em = new EventEmitter();
166
172
  this.channel = null;
167
173
  this.connection = null;
@@ -284,8 +290,8 @@ class RabbitMq implements IAfRabbitMq {
284
290
  }
285
291
  this.creatingConnection = true;
286
292
  let isResolved = false;
287
- debug('rabbit: creating connection', { HOST, USERNAME, HEARTBEAT });
288
- const connection: AmqpConnectionManager = await connect([`amqp://${USERNAME}:${PASSWORD}@${HOST}?heartbeat=${HEARTBEAT}}`]);
293
+ debug('rabbit: creating connection', { host: this.host, userName: this.userName, HEARTBEAT });
294
+ const connection: AmqpConnectionManager = await connect([`amqp://${this.userName}:${this.password}@${this.host}?heartbeat=${HEARTBEAT}}`]);
289
295
  this.connection = connection;
290
296
  this.connection.on('error', (err) => {
291
297
  logger.error('rabbit: connection error', { err });
@@ -309,8 +315,6 @@ class RabbitMq implements IAfRabbitMq {
309
315
  debug('rabbit: connection closed');
310
316
  this.exchanges = {};
311
317
  this.queues = {};
312
- this.connection = null;
313
- this.channel = null;
314
318
  if (this.options?.disableReconnect) {
315
319
  logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
316
320
  this.blockReconnect = true;
@@ -332,7 +336,8 @@ class RabbitMq implements IAfRabbitMq {
332
336
  async getNewChannel({ name = rand().toString(), onClose = null }: newChannelOpts = {}) {
333
337
  return new Promise<ChannelWrapper>(async (resolve, reject) => {
334
338
  const connection: AmqpConnectionManager = await this.getConnection();
335
- const channel = connection.createChannel({});
339
+ const channel = connection.createChannel({
340
+ });
336
341
 
337
342
  let isResolved = false;
338
343
  channel.on('error', (err) => {
@@ -364,9 +369,9 @@ class RabbitMq implements IAfRabbitMq {
364
369
 
365
370
  try {
366
371
  const channel = await this.getNewChannel({
367
- onClose: () => {
368
- this.channel = null;
369
- },
372
+ });
373
+ channel.on('error', (err) => {
374
+ logger.error('rabbit: channel error', { err });
370
375
  });
371
376
  this.channel = channel;
372
377
  resolve(channel);
@@ -604,14 +609,19 @@ class RabbitMq implements IAfRabbitMq {
604
609
  isBlocking?: boolean,
605
610
  ): Promise<boolean | undefined> {
606
611
  const callback = async (): Promise<boolean | undefined> => {
607
- RabbitMq.validateName('queue', queue);
608
- await this.assertChannel();
609
- await this.assertQueue(queue, options);
610
- const res = await this.channel?.sendToQueue(queue,
611
- Buffer.from(JSON.stringify(content)),
612
- RabbitMq.getPublishOptions(customHeaders));
613
- debug(`rabbit: sending to queue ${queue}`, { res });
614
- return res;
612
+ try {
613
+ RabbitMq.validateName('queue', queue);
614
+ await this.assertChannel();
615
+ await this.assertQueue(queue, options);
616
+ const res = await this.channel?.sendToQueue(queue,
617
+ Buffer.from(JSON.stringify(content)),
618
+ RabbitMq.getPublishOptions(customHeaders));
619
+ debug(`rabbit: sending to queue ${queue}`, { res });
620
+ return res;
621
+ } catch (e) {
622
+ logger.error(`rabbit: failed to send to queue ${queue}`, { e });
623
+ throw e;
624
+ }
615
625
  };
616
626
  if (isBlocking) {
617
627
  return callback();