@autofleet/rabbit 2.3.1 → 2.3.4

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
@@ -62,8 +62,8 @@ declare class RabbitMq implements IAfRabbitMq {
62
62
  redisLock?: RedisLockType;
63
63
  constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig);
64
64
  private shouldConsumeMessageByTimestamp;
65
- ack: (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean) => (userMsg: ConsumeMessage) => Promise<any>;
66
- nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: any) => Promise<any>;
65
+ ack: (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
66
+ nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: any) => Promise<any>;
67
67
  getConnection(): Promise<AmqpConnectionManager>;
68
68
  getNewChannel(): Promise<ChannelWrapper>;
69
69
  assertChannel(): Promise<ChannelWrapper>;
@@ -72,7 +72,8 @@ declare class RabbitMq implements IAfRabbitMq {
72
72
  bindQueue(queue: string, exchange: string): Promise<void>;
73
73
  assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
74
74
  consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
75
- private consumeWithLock;
75
+ private lockRedisIfNeeded;
76
+ private unlockRedisIfNeeded;
76
77
  private consumeFromRabbit;
77
78
  consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
78
79
  publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
package/dist/index.js CHANGED
@@ -26,10 +26,13 @@ const redis_1 = __importDefault(require("./redis"));
26
26
  const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
27
27
  const DEFAULT_LOCK_TIMEOUT = 1000 * 5;
28
28
  const RETRY_HEADER = 'x-retry-count';
29
+ const DEFAULT_USE_CONSUME_WITH_LOCK = false;
29
30
  const defaultOptions = {
30
31
  limit: 1,
31
32
  retries: 1,
32
33
  deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,
34
+ lockTimeout: DEFAULT_LOCK_TIMEOUT,
35
+ useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,
33
36
  };
34
37
  const assertExchangeFanout = (c, exchangeName) => c.assertExchange(exchangeName, 'fanout');
35
38
  const connectionCreatedConst = 'connectionCreated';
@@ -62,7 +65,7 @@ class RabbitMq {
62
65
  }
63
66
  return false;
64
67
  });
65
- this.ack = (channel, msg, shouldUpdateRedisTimestamp = false) => (userMsg) => __awaiter(this, void 0, void 0, function* () {
68
+ this.ack = (channel, msg, shouldUpdateRedisTimestamp = false, releaseLock = null) => (userMsg) => __awaiter(this, void 0, void 0, function* () {
66
69
  if (msg) {
67
70
  yield channel.ack(msg);
68
71
  const { properties: { headers } } = msg;
@@ -70,10 +73,12 @@ class RabbitMq {
70
73
  if (shouldUpdateRedisTimestamp && timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey) && this.redisClient) {
71
74
  const parsedTimestamp = parseInt(timestamp, 10);
72
75
  yield this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
76
+ yield this.unlockRedisIfNeeded(releaseLock);
73
77
  }
74
78
  }
75
79
  });
76
- this.nack = (channel, queue, options, deadQueueOptions, msg) => (userMsg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
80
+ this.nack = (channel, queue, options, deadQueueOptions, msg, releaseLock) => (userMsg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
81
+ yield this.unlockRedisIfNeeded(releaseLock);
77
82
  if (channel && msg) {
78
83
  if (!skipRetry
79
84
  && (!msg.properties.headers[RETRY_HEADER]
@@ -223,52 +228,38 @@ class RabbitMq {
223
228
  }
224
229
  consume(queue, callback, options) {
225
230
  return __awaiter(this, void 0, void 0, function* () {
226
- if (options && options.useConsumeWithLock) {
227
- return this.consumeWithLock(queue, callback, options);
228
- }
229
231
  return this.consumeFromRabbit(queue, callback, options);
230
232
  });
231
233
  }
232
- consumeWithLock(queue, callback, options) {
234
+ lockRedisIfNeeded(msg, options) {
233
235
  return __awaiter(this, void 0, void 0, function* () {
234
- if (!this.redisLock) {
235
- throw new Error('Usage of consumeWithLock requires RedisInstance');
236
+ const { properties: { headers } } = msg;
237
+ const timestamp = headers === null || headers === void 0 ? void 0 : headers.creationTimestamp;
238
+ let releaseLock = null;
239
+ if (options.useConsumeWithLock && timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey) && this.redisLock) {
240
+ releaseLock = yield this.redisLock(headers.redisTimestampValidationKey, (options === null || options === void 0 ? void 0 : options.lockTimeout) || DEFAULT_LOCK_TIMEOUT);
241
+ }
242
+ return releaseLock;
243
+ });
244
+ }
245
+ unlockRedisIfNeeded(releaseLock) {
246
+ return __awaiter(this, void 0, void 0, function* () {
247
+ if (this.redisLock && releaseLock) {
248
+ yield releaseLock();
236
249
  }
237
- const lockTimeout = (options === null || options === void 0 ? void 0 : options.lockTimeout) || DEFAULT_LOCK_TIMEOUT;
238
- logger_1.default.info(`Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
239
- return this.consumeFromRabbit(queue, (msg, ack, nack) => __awaiter(this, void 0, void 0, function* () {
240
- logger_1.default.info('Logs ');
241
- if (!msg) {
242
- return null;
243
- }
244
- const { properties: { headers } } = msg;
245
- const timestamp = headers === null || headers === void 0 ? void 0 : headers.creationTimestamp;
246
- let releaseLock = null;
247
- try {
248
- if (timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey)) {
249
- if (this.redisLock) {
250
- releaseLock = yield this.redisLock(headers.redisTimestampValidationKey, lockTimeout);
251
- yield callback(msg, ack, nack);
252
- yield releaseLock();
253
- return;
254
- }
255
- }
256
- yield callback(msg, ack, nack);
257
- }
258
- catch (err) {
259
- if (releaseLock) {
260
- yield releaseLock();
261
- }
262
- throw err;
263
- }
264
- }), options);
265
250
  });
266
251
  }
267
252
  consumeFromRabbit(queue, callback, options) {
268
253
  return __awaiter(this, void 0, void 0, function* () {
269
254
  const optionsWithDefaults = Object.assign(Object.assign({}, defaultOptions), options);
270
255
  RabbitMq.validateName('queue', queue);
271
- const { limit, deadMessageTtl } = optionsWithDefaults;
256
+ const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, } = optionsWithDefaults;
257
+ if (useConsumeWithLock) {
258
+ if (!this.redisLock) {
259
+ throw new Error('Usage of consumeWithLock requires RedisInstance');
260
+ }
261
+ logger_1.default.info(`Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
262
+ }
272
263
  const channel = yield this.getNewChannel();
273
264
  return channel.addSetup((c) => __awaiter(this, void 0, void 0, function* () {
274
265
  yield c.assertQueue(queue);
@@ -279,15 +270,17 @@ class RabbitMq {
279
270
  return null;
280
271
  }
281
272
  const parsedMessage = RabbitMq.parseMsg(msg);
273
+ const releaseLock = yield this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
282
274
  const shouldConsume = yield this.shouldConsumeMessageByTimestamp(parsedMessage);
283
275
  if (!shouldConsume) {
276
+ yield this.unlockRedisIfNeeded(releaseLock);
284
277
  return this.ack(channel, msg)(msg);
285
278
  }
286
279
  try {
287
- yield callback(parsedMessage, this.ack(channel, msg, true), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg));
280
+ yield callback(parsedMessage, this.ack(channel, msg, true, releaseLock), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock));
288
281
  }
289
282
  catch (e) {
290
- yield this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg)(msg);
283
+ yield this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
291
284
  }
292
285
  })),
293
286
  ]);
@@ -325,7 +318,6 @@ class RabbitMq {
325
318
  }
326
319
  sendToQueue(queue, content, options, customHeaders) {
327
320
  return __awaiter(this, void 0, void 0, function* () {
328
- logger_1.default.info('ss', RabbitMq.getPublishOptions(customHeaders));
329
321
  return wrapSetImmediate(() => __awaiter(this, void 0, void 0, function* () {
330
322
  RabbitMq.validateName('queue', queue);
331
323
  const channel = yield this.assertChannel();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "2.3.1",
3
+ "version": "2.3.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -55,11 +55,14 @@ export interface AfRabbitOptions {
55
55
  const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
56
56
  const DEFAULT_LOCK_TIMEOUT = 1000 * 5;
57
57
  const RETRY_HEADER = 'x-retry-count';
58
+ const DEFAULT_USE_CONSUME_WITH_LOCK = false;
58
59
 
59
60
  const defaultOptions = {
60
61
  limit: 1,
61
62
  retries: 1,
62
63
  deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,
64
+ lockTimeout: DEFAULT_LOCK_TIMEOUT,
65
+ useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,
63
66
  };
64
67
 
65
68
  const assertExchangeFanout = (c: any, exchangeName: string) => c.assertExchange(exchangeName, 'fanout');
@@ -162,7 +165,7 @@ class RabbitMq implements IAfRabbitMq {
162
165
  return false;
163
166
  }
164
167
 
165
- public ack = (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false) => async (userMsg: ConsumeMessage) : Promise<any> => {
168
+ public ack = (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage) : Promise<any> => {
166
169
  if (msg) {
167
170
  await channel.ack(msg);
168
171
  const { properties: { headers } } = msg;
@@ -171,6 +174,7 @@ class RabbitMq implements IAfRabbitMq {
171
174
  if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {
172
175
  const parsedTimestamp = parseInt(timestamp, 10);
173
176
  await this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
177
+ await this.unlockRedisIfNeeded(releaseLock);
174
178
  }
175
179
  }
176
180
  }
@@ -181,12 +185,14 @@ class RabbitMq implements IAfRabbitMq {
181
185
  options: any,
182
186
  deadQueueOptions: Options.AssertQueue,
183
187
  msg: ConsumeMessageOrNull,
188
+ releaseLock: any,
184
189
  ) => async (
185
190
  userMsg: ConsumeMessageOrNull,
186
191
  {
187
192
  skipRetry = false,
188
193
  }: any = { },
189
194
  ) : Promise<any> => {
195
+ await this.unlockRedisIfNeeded(releaseLock);
190
196
  if (channel && msg) {
191
197
  if (
192
198
  !skipRetry
@@ -305,53 +311,41 @@ class RabbitMq implements IAfRabbitMq {
305
311
  }
306
312
 
307
313
  async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
308
- if (options && options.useConsumeWithLock) {
309
- return this.consumeWithLock(queue, callback, options);
310
- }
311
314
  return this.consumeFromRabbit(queue, callback, options);
312
315
  }
313
316
 
314
- private async consumeWithLock(queue: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<any> {
315
- if (!this.redisLock) {
316
- throw new Error('Usage of consumeWithLock requires RedisInstance');
317
+ private async lockRedisIfNeeded(msg: any, options: any) {
318
+ const { properties: { headers } } = msg;
319
+ const timestamp = headers?.creationTimestamp;
320
+ let releaseLock = null;
321
+
322
+ if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {
323
+ releaseLock = await this.redisLock(
324
+ headers.redisTimestampValidationKey,
325
+ options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,
326
+ );
317
327
  }
318
- const lockTimeout = options?.lockTimeout || DEFAULT_LOCK_TIMEOUT;
319
- logger.info(`Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
320
- return this.consumeFromRabbit(queue, async (msg, ack, nack) => {
321
- logger.info('Logs ');
322
- if (!msg) {
323
- return null;
324
- }
325
- const { properties: { headers } } = msg;
326
- const timestamp = headers?.creationTimestamp;
327
- let releaseLock = null;
328
+ return releaseLock;
329
+ }
328
330
 
329
- try {
330
- if (timestamp && headers?.redisTimestampValidationKey) {
331
- if (this.redisLock) {
332
- releaseLock = await this.redisLock(
333
- headers.redisTimestampValidationKey,
334
- lockTimeout,
335
- );
336
- await callback(msg, ack, nack);
337
- await releaseLock();
338
- return;
339
- }
340
- }
341
- await callback(msg, ack, nack);
342
- } catch (err) {
343
- if (releaseLock) {
344
- await releaseLock();
345
- }
346
- throw err;
347
- }
348
- }, options);
331
+ private async unlockRedisIfNeeded(releaseLock: any) {
332
+ if (this.redisLock && releaseLock) {
333
+ await releaseLock();
334
+ }
349
335
  }
350
336
 
351
337
  private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
352
338
  const optionsWithDefaults = { ...defaultOptions, ...options };
353
339
  RabbitMq.validateName('queue', queue);
354
- const { limit, deadMessageTtl } = optionsWithDefaults;
340
+ const {
341
+ limit, deadMessageTtl, useConsumeWithLock, lockTimeout,
342
+ } = optionsWithDefaults;
343
+ if (useConsumeWithLock) {
344
+ if (!this.redisLock) {
345
+ throw new Error('Usage of consumeWithLock requires RedisInstance');
346
+ }
347
+ logger.info(`Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
348
+ }
355
349
  const channel: ChannelWrapper = await this.getNewChannel();
356
350
  return channel.addSetup(async (c: ConfirmChannel) => {
357
351
  await c.assertQueue(queue);
@@ -364,18 +358,20 @@ class RabbitMq implements IAfRabbitMq {
364
358
  return null;
365
359
  }
366
360
  const parsedMessage = RabbitMq.parseMsg(msg);
361
+ const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
367
362
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
368
363
  if (!shouldConsume) {
364
+ await this.unlockRedisIfNeeded(releaseLock);
369
365
  return this.ack(channel, msg)(msg);
370
366
  }
371
367
  try {
372
368
  await callback(
373
369
  parsedMessage,
374
- this.ack(channel, msg, true),
375
- this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg),
370
+ this.ack(channel, msg, true, releaseLock),
371
+ this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock),
376
372
  );
377
373
  } catch (e) {
378
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg)(msg);
374
+ await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
379
375
  }
380
376
  },
381
377
  ),
@@ -418,7 +414,6 @@ class RabbitMq implements IAfRabbitMq {
418
414
  }
419
415
 
420
416
  async sendToQueue(queue: string, content: any, options?: any, customHeaders?: any) : Promise<boolean> {
421
- logger.info('ss', RabbitMq.getPublishOptions(customHeaders));
422
417
  return wrapSetImmediate(async () => {
423
418
  RabbitMq.validateName('queue', queue);
424
419
  const channel: ChannelWrapper = await this.assertChannel();