@autofleet/rabbit 3.2.2 → 3.2.4-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/dist/index.d.ts CHANGED
@@ -17,6 +17,9 @@ export interface IAfRabbitMq {
17
17
  sendToQueue: any;
18
18
  redisClient?: any;
19
19
  }
20
+ interface NackOptions {
21
+ skipRetry?: boolean;
22
+ }
20
23
  export interface AfRabbitOptions {
21
24
  disableReconnect?: boolean;
22
25
  /**
@@ -69,8 +72,8 @@ declare class RabbitMq implements IAfRabbitMq {
69
72
  private consumers;
70
73
  constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig);
71
74
  private shouldConsumeMessageByTimestamp;
72
- ack: (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
73
- nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: any) => Promise<any>;
75
+ ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
76
+ nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
74
77
  getConnection(): Promise<AmqpConnectionManager>;
75
78
  getNewChannel({ name, onClose }?: newChannelOpts): Promise<ChannelWrapper>;
76
79
  assertChannel({ force }?: assertChannelOpts): Promise<ChannelWrapper>;
@@ -80,7 +83,6 @@ declare class RabbitMq implements IAfRabbitMq {
80
83
  bindQueue(queue: string, exchange: string): Promise<void>;
81
84
  assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
82
85
  private saveConsumer;
83
- private loadConsumers;
84
86
  consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
85
87
  private lockRedisIfNeeded;
86
88
  private unlockRedisIfNeeded;
package/dist/index.js CHANGED
@@ -75,7 +75,6 @@ class RabbitMq {
75
75
  }
76
76
  else {
77
77
  logger_1.default.error('no channel or msg', {
78
- channel: channel ? channel.name : '',
79
78
  msg,
80
79
  });
81
80
  }
@@ -160,6 +159,9 @@ class RabbitMq {
160
159
  }
161
160
  this.creatingConnection = true;
162
161
  let isResolved = false;
162
+ // It is import to use it as a function and not as a variable
163
+ // because of k8s changes the env variables
164
+ // and we want to use the new values
163
165
  const findServers = () => {
164
166
  const userName = process.env.RABBITMQ_USERNAME || 'guest';
165
167
  const password = process.env.RABBITMQ_PASSWORD || 'guest';
@@ -190,8 +192,6 @@ class RabbitMq {
190
192
  });
191
193
  this.connection.on('disconnect', ({ err }) => {
192
194
  debug('rabbit: connection closed');
193
- this.exchanges = {};
194
- this.queues = {};
195
195
  if (this.options?.disableReconnect) {
196
196
  logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
197
197
  this.blockReconnect = true;
@@ -202,7 +202,6 @@ class RabbitMq {
202
202
  });
203
203
  this.connection.once('connect', async () => {
204
204
  debug('rabbit: connection established');
205
- await this.loadConsumers();
206
205
  this.creatingConnection = false;
207
206
  this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
208
207
  isResolved = true;
@@ -216,7 +215,7 @@ class RabbitMq {
216
215
  const channel = connection.createChannel({});
217
216
  let isResolved = false;
218
217
  channel.on('error', (err) => {
219
- logger_1.default.error(`rabbit: channel ${name} error`, { err });
218
+ logger_1.default.error(`rabbit: channel error ${name} error`, { err });
220
219
  if (!isResolved) {
221
220
  isResolved = true;
222
221
  reject(err);
@@ -264,9 +263,12 @@ class RabbitMq {
264
263
  }
265
264
  async getQueueLength(queue) {
266
265
  RabbitMq.validateName('queue', queue);
267
- const channel = await this.assertChannel();
266
+ const { channel } = this;
267
+ if (!channel) {
268
+ throw new Error('channel is not defined');
269
+ }
268
270
  debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
269
- return channel.checkQueue(queue);
271
+ return channel?.checkQueue(queue);
270
272
  }
271
273
  async deleteQueue(queue) {
272
274
  RabbitMq.validateName('queue', queue);
@@ -319,18 +321,8 @@ class RabbitMq {
319
321
  options,
320
322
  });
321
323
  }
322
- async loadConsumers() {
323
- debug('rabbit: loading consumers', { consumers: this.consumers.length });
324
- if (this.consumers.length > 0) {
325
- await Promise.all(this.consumers.map((consumer) => this
326
- .consumeFromRabbit(consumer.queue, consumer.callback, consumer.options)));
327
- }
328
- }
329
324
  async consume(queue, callback, options) {
330
- if (this.connection && !this.creatingConnection) {
331
- this.consumeFromRabbit(queue, callback, options);
332
- }
333
- return this.saveConsumer(queue, callback, options);
325
+ return this.consumeFromRabbit(queue, callback, options);
334
326
  }
335
327
  async lockRedisIfNeeded(msg, options) {
336
328
  const { properties: { headers } } = msg;
@@ -357,10 +349,10 @@ class RabbitMq {
357
349
  logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
358
350
  }
359
351
  const channel = await this.getNewChannel({ name: `consume-queue-${queue}` });
360
- return channel.addSetup(async (c) => {
361
- await c.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
362
- await c.prefetch(limit, true);
363
- const { consumerTag } = await c.consume(queue, async (msg) => {
352
+ return channel.addSetup(async (confirmChannel) => {
353
+ await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
354
+ await confirmChannel.prefetch(limit, true);
355
+ const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
364
356
  if (!msg) {
365
357
  return null;
366
358
  }
@@ -382,7 +374,7 @@ class RabbitMq {
382
374
  }
383
375
  catch (e) {
384
376
  logger_1.default.error('rabbit: failed to setRabbitTrace', { userId, e });
385
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
377
+ await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
386
378
  }
387
379
  }
388
380
  if (traceId) {
@@ -395,13 +387,29 @@ class RabbitMq {
395
387
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
396
388
  if (!shouldConsume) {
397
389
  await this.unlockRedisIfNeeded(releaseLock);
398
- return this.ack(channel, msg)(msg);
390
+ return this.ack(confirmChannel, msg)(msg);
399
391
  }
392
+ let messageAcked = false;
393
+ // setting the localAck function to be used in the callback
394
+ const localAck = async () => {
395
+ if (messageAcked) {
396
+ return;
397
+ }
398
+ messageAcked = true;
399
+ return this.ack(confirmChannel, msg, true, releaseLock)(msg);
400
+ };
401
+ const localNack = async (_, nackOptions = {}) => {
402
+ if (messageAcked) {
403
+ return;
404
+ }
405
+ messageAcked = true;
406
+ return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);
407
+ };
400
408
  try {
401
- await callback(parsedMessage, this.ack(channel, msg, true, releaseLock), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock));
409
+ await callback(parsedMessage, localAck, localNack);
402
410
  }
403
411
  catch (e) {
404
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
412
+ await localNack(msg);
405
413
  }
406
414
  }, types_1.CONSUMER_DEFAULT_OPTIONS);
407
415
  if (!consumerTag) {
@@ -409,7 +417,7 @@ class RabbitMq {
409
417
  }
410
418
  else {
411
419
  logger_1.default.info(`rabbit: adding tag ${consumerTag} to the array.`);
412
- this.consumersTags.push([c, consumerTag]);
420
+ this.consumersTags.push([confirmChannel, consumerTag]);
413
421
  }
414
422
  });
415
423
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.2.2",
3
+ "version": "3.2.4-beta.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -53,6 +53,10 @@ export interface IAfRabbitMq {
53
53
  redisClient?: any;
54
54
  }
55
55
 
56
+ interface NackOptions {
57
+ skipRetry?: boolean;
58
+ }
59
+
56
60
  export interface AfRabbitOptions {
57
61
  disableReconnect?: boolean;
58
62
 
@@ -194,7 +198,7 @@ class RabbitMq implements IAfRabbitMq {
194
198
  return false;
195
199
  }
196
200
 
197
- public ack = (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage) : Promise<any> => {
201
+ public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage) : Promise<any> => {
198
202
  if (msg) {
199
203
  await channel.ack(msg);
200
204
  const { properties: { headers } } = msg;
@@ -209,7 +213,7 @@ class RabbitMq implements IAfRabbitMq {
209
213
  }
210
214
 
211
215
  public nack = (
212
- channel: ChannelWrapper,
216
+ channel: ConfirmChannel,
213
217
  queue: string,
214
218
  options: any,
215
219
  deadQueueOptions: Options.AssertQueue,
@@ -219,7 +223,7 @@ class RabbitMq implements IAfRabbitMq {
219
223
  userMsg: ConsumeMessageOrNull,
220
224
  {
221
225
  skipRetry = false,
222
- }: any = { },
226
+ }: NackOptions = { },
223
227
  ) : Promise<any> => {
224
228
  await this.unlockRedisIfNeeded(releaseLock);
225
229
  if (channel && msg) {
@@ -248,7 +252,6 @@ class RabbitMq implements IAfRabbitMq {
248
252
  await channel.ack(msg);
249
253
  } else {
250
254
  logger.error('no channel or msg', {
251
- channel: channel ? channel.name : '',
252
255
  msg,
253
256
  });
254
257
  }
@@ -280,6 +283,9 @@ class RabbitMq implements IAfRabbitMq {
280
283
  this.creatingConnection = true;
281
284
  let isResolved = false;
282
285
 
286
+ // It is import to use it as a function and not as a variable
287
+ // because of k8s changes the env variables
288
+ // and we want to use the new values
283
289
  const findServers = () => {
284
290
  const userName = process.env.RABBITMQ_USERNAME || 'guest';
285
291
  const password = process.env.RABBITMQ_PASSWORD || 'guest';
@@ -316,8 +322,6 @@ class RabbitMq implements IAfRabbitMq {
316
322
 
317
323
  this.connection.on('disconnect', ({ err }) => {
318
324
  debug('rabbit: connection closed');
319
- this.exchanges = {};
320
- this.queues = {};
321
325
  if (this.options?.disableReconnect) {
322
326
  logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
323
327
  this.blockReconnect = true;
@@ -327,7 +331,6 @@ class RabbitMq implements IAfRabbitMq {
327
331
  });
328
332
  this.connection.once('connect', async () => {
329
333
  debug('rabbit: connection established');
330
- await this.loadConsumers();
331
334
  this.creatingConnection = false;
332
335
  this.em.emit(CONNECTION_CREATED_CONST, connection);
333
336
  isResolved = true;
@@ -344,7 +347,7 @@ class RabbitMq implements IAfRabbitMq {
344
347
 
345
348
  let isResolved = false;
346
349
  channel.on('error', (err) => {
347
- logger.error(`rabbit: channel ${name} error`, { err });
350
+ logger.error(`rabbit: channel error ${name} error`, { err });
348
351
  if (!isResolved) {
349
352
  isResolved = true;
350
353
  reject(err);
@@ -396,9 +399,12 @@ class RabbitMq implements IAfRabbitMq {
396
399
 
397
400
  async getQueueLength(queue: string) {
398
401
  RabbitMq.validateName('queue', queue);
399
- const channel: ChannelWrapper = await this.assertChannel();
402
+ const { channel } = this;
403
+ if (!channel) {
404
+ throw new Error('channel is not defined');
405
+ }
400
406
  debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
401
- return channel.checkQueue(queue);
407
+ return channel?.checkQueue(queue);
402
408
  }
403
409
 
404
410
  private async deleteQueue(queue: string) {
@@ -456,21 +462,8 @@ class RabbitMq implements IAfRabbitMq {
456
462
  });
457
463
  }
458
464
 
459
- private async loadConsumers() {
460
- debug('rabbit: loading consumers', { consumers: this.consumers.length });
461
- if (this.consumers.length > 0) {
462
- await Promise.all(
463
- this.consumers.map((consumer) => this
464
- .consumeFromRabbit(consumer.queue, consumer.callback, consumer.options)),
465
- );
466
- }
467
- }
468
-
469
465
  async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
470
- if (this.connection && !this.creatingConnection) {
471
- this.consumeFromRabbit(queue, callback, options);
472
- }
473
- return this.saveConsumer(queue, callback, options);
466
+ return this.consumeFromRabbit(queue, callback, options);
474
467
  }
475
468
 
476
469
  private async lockRedisIfNeeded(msg: any, options: any) {
@@ -506,10 +499,10 @@ class RabbitMq implements IAfRabbitMq {
506
499
  logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
507
500
  }
508
501
  const channel: ChannelWrapper = await this.getNewChannel({ name: `consume-queue-${queue}` });
509
- return channel.addSetup(async (c: ConfirmChannel) => {
510
- await c.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
511
- await c.prefetch(limit, true);
512
- const { consumerTag } = await c.consume(
502
+ return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
503
+ await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
504
+ await confirmChannel.prefetch(limit, true);
505
+ const { consumerTag } = await confirmChannel.consume(
513
506
  queue,
514
507
  async (msg: ConsumeMessageOrNull) => {
515
508
  if (!msg) {
@@ -533,7 +526,7 @@ class RabbitMq implements IAfRabbitMq {
533
526
  ]);
534
527
  } catch (e) {
535
528
  logger.error('rabbit: failed to setRabbitTrace', { userId, e });
536
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
529
+ await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
537
530
  }
538
531
  }
539
532
 
@@ -548,16 +541,36 @@ class RabbitMq implements IAfRabbitMq {
548
541
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
549
542
  if (!shouldConsume) {
550
543
  await this.unlockRedisIfNeeded(releaseLock);
551
- return this.ack(channel, msg)(msg);
544
+ return this.ack(confirmChannel, msg)(msg);
552
545
  }
546
+
547
+ let messageAcked = false;
548
+ // setting the localAck function to be used in the callback
549
+
550
+ const localAck = async () => {
551
+ if (messageAcked) {
552
+ return;
553
+ }
554
+ messageAcked = true;
555
+ return this.ack(confirmChannel, msg, true, releaseLock)(msg);
556
+ };
557
+
558
+ const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {
559
+ if (messageAcked) {
560
+ return;
561
+ }
562
+ messageAcked = true;
563
+ return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);
564
+ };
565
+
553
566
  try {
554
567
  await callback(
555
568
  parsedMessage,
556
- this.ack(channel, msg, true, releaseLock),
557
- this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock),
569
+ localAck,
570
+ localNack,
558
571
  );
559
572
  } catch (e) {
560
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
573
+ await localNack(msg);
561
574
  }
562
575
  }, CONSUMER_DEFAULT_OPTIONS,
563
576
  );
@@ -565,7 +578,7 @@ class RabbitMq implements IAfRabbitMq {
565
578
  logger.error(`rabbit: failed to consume from queue ${queue}`);
566
579
  } else {
567
580
  logger.info(`rabbit: adding tag ${consumerTag} to the array.`);
568
- this.consumersTags.push([c, consumerTag]);
581
+ this.consumersTags.push([confirmChannel, consumerTag]);
569
582
  }
570
583
  });
571
584
  }