@autofleet/rabbit 2.2.4-beta-2 → 2.2.6

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
@@ -25,6 +25,7 @@ declare type CustomMessageHeaders = {
25
25
  redisTimestampValidationKey?: string;
26
26
  };
27
27
  declare type RedisLockType = (args0?: string, arg1?: number) => Promise<any>;
28
+ declare type ConsumeMessageOrNull = ConsumeMessage | null;
28
29
  interface ConsumeOptions {
29
30
  retries?: number;
30
31
  deadMessageTtl?: number;
@@ -58,8 +59,8 @@ declare class RabbitMq implements IAfRabbitMq {
58
59
  redisLock?: RedisLockType;
59
60
  constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig);
60
61
  private shouldConsumeMessageByTimestamp;
61
- ack: (channel: ChannelWrapper, shouldUpdateRedisTimestamp?: boolean) => (msg: ConsumeMessage) => Promise<any>;
62
- nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue) => (msg: any, { skipRetry, }?: any) => Promise<void>;
62
+ ack: (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean) => (userMsg: ConsumeMessage) => Promise<any>;
63
+ nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: any) => Promise<any>;
63
64
  getConnection(): Promise<AmqpConnectionManager>;
64
65
  getNewChannel(): Promise<ChannelWrapper>;
65
66
  assertChannel(): Promise<ChannelWrapper>;
@@ -71,7 +72,7 @@ declare class RabbitMq implements IAfRabbitMq {
71
72
  private consumeWithLock;
72
73
  private consumeFromRabbit;
73
74
  consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
74
- publish(exchange: string, content: any, customHeaders?: any): Promise<any>;
75
+ publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
75
76
  sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean>;
76
77
  isConnected(): Promise<boolean>;
77
78
  }
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ const rabbitError_1 = __importDefault(require("./rabbitError"));
25
25
  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
+ const RETRY_HEADER = 'x-retry-count';
28
29
  const defaultOptions = {
29
30
  limit: 1,
30
31
  retries: 1,
@@ -32,6 +33,17 @@ const defaultOptions = {
32
33
  };
33
34
  const assertExchangeFanout = (c, exchangeName) => c.assertExchange(exchangeName, 'fanout');
34
35
  const connectionCreatedConst = 'connectionCreated';
36
+ const wrapSetImmediate = (callback) => new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () {
37
+ setImmediate(() => __awaiter(void 0, void 0, void 0, function* () {
38
+ try {
39
+ const value = yield callback();
40
+ resolve(value);
41
+ }
42
+ catch (error) {
43
+ reject(error);
44
+ }
45
+ }));
46
+ }));
35
47
  class RabbitMq {
36
48
  constructor(options, redisConfig) {
37
49
  this.PUBLISH_TIMEOUT = Number(process.env.RABBITMQ_PUBLISH_TIMEOUT) || 60000;
@@ -52,26 +64,34 @@ class RabbitMq {
52
64
  }
53
65
  return false;
54
66
  });
55
- this.ack = (channel, shouldUpdateRedisTimestamp = false) => (msg) => __awaiter(this, void 0, void 0, function* () {
56
- yield channel.ack(msg);
57
- const { properties: { timestamp, headers } } = msg;
58
- if (shouldUpdateRedisTimestamp && timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey) && this.redisClient) {
59
- const parsedTimestamp = parseInt(timestamp, 10);
60
- yield this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
67
+ this.ack = (channel, msg, shouldUpdateRedisTimestamp = false) => (userMsg) => __awaiter(this, void 0, void 0, function* () {
68
+ if (msg) {
69
+ yield channel.ack(msg);
70
+ const { properties: { timestamp, headers } } = msg;
71
+ if (shouldUpdateRedisTimestamp && timestamp && (headers === null || headers === void 0 ? void 0 : headers.redisTimestampValidationKey) && this.redisClient) {
72
+ const parsedTimestamp = parseInt(timestamp, 10);
73
+ yield this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
74
+ }
61
75
  }
62
76
  });
63
- this.nack = (channel, queue, options, deadQueueOptions) => (msg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
64
- if (channel) {
77
+ this.nack = (channel, queue, options, deadQueueOptions, msg) => (userMsg, { skipRetry = false, } = {}) => __awaiter(this, void 0, void 0, function* () {
78
+ if (channel && msg) {
65
79
  if (!skipRetry
66
- && (!msg.content['x-retry-count']
67
- || msg.content['x-retry-count'] < options.retries)) {
68
- msg.content['x-retry-count'] = msg.content['x-retry-count'] ? msg.content['x-retry-count'] + 1 : 1;
69
- yield this.sendToQueue(queue, msg.content);
80
+ && (!msg.properties.headers[RETRY_HEADER]
81
+ || parseInt(msg.properties.headers[RETRY_HEADER], 10) < options.retries)) {
82
+ yield this.sendToQueue(queue, RabbitMq.parseMsg(msg).content, options, {
83
+ [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
84
+ ? msg.properties.headers[RETRY_HEADER] + 1
85
+ : 1,
86
+ });
70
87
  }
71
88
  else {
72
89
  const deadQueue = `${queue}-dead`;
73
- yield this.assertQueue(deadQueue, deadQueueOptions);
74
- yield this.sendToQueue(deadQueue, msg.content, deadQueueOptions);
90
+ yield this.sendToQueue(deadQueue, RabbitMq.parseMsg(msg).content, deadQueueOptions, {
91
+ [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
92
+ ? msg.properties.headers[RETRY_HEADER] + 1
93
+ : 1,
94
+ });
75
95
  }
76
96
  yield channel.ack(msg);
77
97
  }
@@ -264,13 +284,13 @@ class RabbitMq {
264
284
  const shouldConsume = yield this.shouldConsumeMessageByTimestamp(parsedMessage);
265
285
  logger_1.default.info('rabbit: trying to consume', { queue, shouldConsume, msg });
266
286
  if (!shouldConsume) {
267
- return this.ack(channel)(msg);
287
+ return this.ack(channel, msg)(msg);
268
288
  }
269
289
  try {
270
- yield callback(parsedMessage, this.ack(channel, true), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
290
+ yield callback(parsedMessage, this.ack(channel, msg, true), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg));
271
291
  }
272
292
  catch (e) {
273
- yield this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl })(msg);
293
+ yield this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg)(msg);
274
294
  }
275
295
  })),
276
296
  ]);
@@ -298,29 +318,23 @@ class RabbitMq {
298
318
  }
299
319
  publish(exchange, content, customHeaders) {
300
320
  return __awaiter(this, void 0, void 0, function* () {
301
- return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
302
- setImmediate(() => __awaiter(this, void 0, void 0, function* () {
303
- try {
304
- RabbitMq.validateName('exchange', exchange);
305
- const channel = yield this.assertChannel();
306
- yield this.assertExchange(exchange);
307
- yield channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
308
- resolve(true);
309
- }
310
- catch (error) {
311
- reject(error);
312
- }
313
- }));
321
+ return wrapSetImmediate(() => __awaiter(this, void 0, void 0, function* () {
322
+ RabbitMq.validateName('exchange', exchange);
323
+ const channel = yield this.assertChannel();
324
+ yield this.assertExchange(exchange);
325
+ yield channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
314
326
  }));
315
327
  });
316
328
  }
317
329
  sendToQueue(queue, content, options, customHeaders) {
318
330
  return __awaiter(this, void 0, void 0, function* () {
319
- RabbitMq.validateName('queue', queue);
320
- const channel = yield this.assertChannel();
321
- yield this.assertQueue(queue, options);
322
- logger_1.default.info('rabbit: sending to queue', { queue, content, customHeaders });
323
- return channel.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
331
+ return wrapSetImmediate(() => __awaiter(this, void 0, void 0, function* () {
332
+ RabbitMq.validateName('queue', queue);
333
+ const channel = yield this.assertChannel();
334
+ yield this.assertQueue(queue, options);
335
+ logger_1.default.info('rabbit: sending to queue', { queue, content, customHeaders });
336
+ return channel.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
337
+ }));
324
338
  });
325
339
  }
326
340
  isConnected() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "2.2.4-beta-2",
3
+ "version": "2.2.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.ts CHANGED
@@ -54,6 +54,7 @@ export interface AfRabbitOptions {
54
54
 
55
55
  const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
56
56
  const DEFAULT_LOCK_TIMEOUT = 1000 * 5;
57
+ const RETRY_HEADER = 'x-retry-count';
57
58
 
58
59
  const defaultOptions = {
59
60
  limit: 1,
@@ -65,6 +66,17 @@ const assertExchangeFanout = (c: any, exchangeName: string) => c.assertExchange(
65
66
 
66
67
  const connectionCreatedConst = 'connectionCreated';
67
68
 
69
+ const wrapSetImmediate = (callback: () => any) => new Promise<any>(async (resolve, reject) => {
70
+ setImmediate(async () => {
71
+ try {
72
+ const value = await callback();
73
+ resolve(value);
74
+ } catch (error) {
75
+ reject(error);
76
+ }
77
+ });
78
+ });
79
+
68
80
  class RabbitMq implements IAfRabbitMq {
69
81
  static parseMsg(msg: any) : any {
70
82
  let { content } = msg;
@@ -148,12 +160,14 @@ class RabbitMq implements IAfRabbitMq {
148
160
  return false;
149
161
  }
150
162
 
151
- public ack = (channel: ChannelWrapper, shouldUpdateRedisTimestamp = false) => async (msg: ConsumeMessage) : Promise<any> => {
152
- await channel.ack(msg);
153
- const { properties: { timestamp, headers } } = msg;
154
- if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {
155
- const parsedTimestamp = parseInt(timestamp, 10);
156
- await this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
163
+ public ack = (channel: ChannelWrapper, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false) => async (userMsg: ConsumeMessage) : Promise<any> => {
164
+ if (msg) {
165
+ await channel.ack(msg);
166
+ const { properties: { timestamp, headers } } = msg;
167
+ if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {
168
+ const parsedTimestamp = parseInt(timestamp, 10);
169
+ await this.redisClient.setAsync(headers.redisTimestampValidationKey, parsedTimestamp, 'EX', 3600);
170
+ }
157
171
  }
158
172
  }
159
173
 
@@ -162,24 +176,33 @@ class RabbitMq implements IAfRabbitMq {
162
176
  queue: string,
163
177
  options: any,
164
178
  deadQueueOptions: Options.AssertQueue,
179
+ msg: ConsumeMessageOrNull,
165
180
  ) => async (
166
- msg: any,
181
+ userMsg: ConsumeMessageOrNull,
167
182
  {
168
183
  skipRetry = false,
169
184
  }: any = { },
170
- ) => {
171
- if (channel) {
185
+ ) : Promise<any> => {
186
+ if (channel && msg) {
172
187
  if (
173
188
  !skipRetry
174
- && (!msg.content['x-retry-count']
175
- || msg.content['x-retry-count'] < options.retries)
189
+ && (
190
+ !msg.properties.headers[RETRY_HEADER]
191
+ || parseInt(msg.properties.headers[RETRY_HEADER], 10) < options.retries
192
+ )
176
193
  ) {
177
- msg.content['x-retry-count'] = msg.content['x-retry-count'] ? msg.content['x-retry-count'] + 1 : 1;
178
- await this.sendToQueue(queue, msg.content);
194
+ await this.sendToQueue(queue, RabbitMq.parseMsg(msg).content, options, {
195
+ [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
196
+ ? msg.properties.headers[RETRY_HEADER] + 1
197
+ : 1,
198
+ });
179
199
  } else {
180
200
  const deadQueue = `${queue}-dead`;
181
- await this.assertQueue(deadQueue, deadQueueOptions);
182
- await this.sendToQueue(deadQueue, msg.content, deadQueueOptions);
201
+ await this.sendToQueue(deadQueue, RabbitMq.parseMsg(msg).content, deadQueueOptions, {
202
+ [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
203
+ ? msg.properties.headers[RETRY_HEADER] + 1
204
+ : 1,
205
+ });
183
206
  }
184
207
  await channel.ack(msg);
185
208
  }
@@ -334,16 +357,16 @@ class RabbitMq implements IAfRabbitMq {
334
357
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
335
358
  logger.info('rabbit: trying to consume', { queue, shouldConsume, msg });
336
359
  if (!shouldConsume) {
337
- return this.ack(channel)(msg);
360
+ return this.ack(channel, msg)(msg);
338
361
  }
339
362
  try {
340
363
  await callback(
341
364
  parsedMessage,
342
- this.ack(channel, true),
343
- this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }),
365
+ this.ack(channel, msg, true),
366
+ this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg),
344
367
  );
345
368
  } catch (e) {
346
- await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl })(msg);
369
+ await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg)(msg);
347
370
  }
348
371
  },
349
372
  ),
@@ -374,32 +397,27 @@ class RabbitMq implements IAfRabbitMq {
374
397
  });
375
398
  }
376
399
 
377
- async publish(exchange: string, content: any, customHeaders?: any) : Promise<any> {
378
- return new Promise<any>(async (resolve, reject) => {
379
- setImmediate(async () => {
380
- try {
381
- RabbitMq.validateName('exchange', exchange);
382
- const channel: ChannelWrapper = await this.assertChannel();
383
- await this.assertExchange(exchange);
384
- await channel.publish(exchange, '',
385
- Buffer.from(JSON.stringify(content)),
386
- RabbitMq.getPublishOptions(customHeaders));
387
- resolve(true);
388
- } catch (error) {
389
- reject(error);
390
- }
391
- });
400
+ async publish(exchange: string, content: any, customHeaders?: any) : Promise<boolean> {
401
+ return wrapSetImmediate(async () => {
402
+ RabbitMq.validateName('exchange', exchange);
403
+ const channel: ChannelWrapper = await this.assertChannel();
404
+ await this.assertExchange(exchange);
405
+ await channel.publish(exchange, '',
406
+ Buffer.from(JSON.stringify(content)),
407
+ RabbitMq.getPublishOptions(customHeaders));
392
408
  });
393
409
  }
394
410
 
395
411
  async sendToQueue(queue: string, content: any, options?: any, customHeaders?: any) : Promise<boolean> {
396
- RabbitMq.validateName('queue', queue);
397
- const channel: ChannelWrapper = await this.assertChannel();
398
- await this.assertQueue(queue, options);
399
- logger.info('rabbit: sending to queue', { queue, content, customHeaders });
400
- return channel.sendToQueue(queue,
401
- Buffer.from(JSON.stringify(content)),
402
- RabbitMq.getPublishOptions(customHeaders));
412
+ return wrapSetImmediate(async () => {
413
+ RabbitMq.validateName('queue', queue);
414
+ const channel: ChannelWrapper = await this.assertChannel();
415
+ await this.assertQueue(queue, options);
416
+ logger.info('rabbit: sending to queue', { queue, content, customHeaders });
417
+ return channel.sendToQueue(queue,
418
+ Buffer.from(JSON.stringify(content)),
419
+ RabbitMq.getPublishOptions(customHeaders));
420
+ });
403
421
  }
404
422
 
405
423
  async isConnected() : Promise<boolean> {
package/tsconfig.json CHANGED
@@ -5,7 +5,9 @@
5
5
  "declaration": true,
6
6
  "outDir": "./dist",
7
7
  "strict": true,
8
- "esModuleInterop": true
8
+ "esModuleInterop": true,
9
+ "experimentalDecorators": true,
10
+ "emitDecoratorMetadata": true
9
11
  },
10
12
  "exclude": ["node_modules", "**/*.test.ts"]
11
13
  }
package/.env DELETED
File without changes
package/dump.rdb DELETED
Binary file