@autofleet/rabbit 1.6.0 → 1.6.1

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
@@ -11,10 +11,6 @@ export interface AfRabbitOptions {
11
11
  declare class RabbitMq {
12
12
  static parseMsg(msg: any): any;
13
13
  static validateName(type: string, name: string): void;
14
- static consumeOptions(options?: any): {
15
- limit: number;
16
- deadMessageTtl: number;
17
- };
18
14
  PUBLISH_TIMEOUT: number;
19
15
  PUBLISH_ERROR_MSG: string;
20
16
  DISCONNECT_MSG: string;
@@ -27,7 +23,7 @@ declare class RabbitMq {
27
23
  options: AfRabbitOptions | undefined;
28
24
  constructor(options?: AfRabbitOptions);
29
25
  ack: (msg: any) => Promise<void>;
30
- nack: (queue: string, deadQueueOptions?: Options.AssertQueue | undefined) => (msg: any, retries: number) => Promise<void>;
26
+ nack: (queue: string, options: any, deadQueueOptions: Options.AssertQueue) => (msg: any) => Promise<void>;
31
27
  getConnection(): Promise<AmqpConnectionManager>;
32
28
  assertChannel(): Promise<ChannelWrapper>;
33
29
  assertExchange(exchangeName: string, options?: any): Promise<any>;
package/dist/index.js CHANGED
@@ -38,6 +38,12 @@ const amqp_connection_manager_1 = require("amqp-connection-manager");
38
38
  const events_1 = require("events");
39
39
  const outbreak_1 = require("@autofleet/outbreak");
40
40
  const rabbitError_1 = __importDefault(require("./rabbitError"));
41
+ const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
42
+ const defaultOptions = {
43
+ limit: 1,
44
+ retries: 1,
45
+ deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,
46
+ };
41
47
  const assertExchangeFanout = (c, exchangeName) => c.assertExchange(exchangeName, 'fanout');
42
48
  const connectionCreatedConst = 'connectionCreated';
43
49
  class RabbitMq {
@@ -51,9 +57,9 @@ class RabbitMq {
51
57
  yield this.channel.ack(msg);
52
58
  }
53
59
  });
54
- this.nack = (queue, deadQueueOptions) => (msg, retries) => __awaiter(this, void 0, void 0, function* () {
60
+ this.nack = (queue, options, deadQueueOptions) => (msg) => __awaiter(this, void 0, void 0, function* () {
55
61
  if (this.channel) {
56
- if (!msg.content['x-retry-count'] || msg.content['x-retry-count'] <= retries) {
62
+ if (!msg.content['x-retry-count'] || msg.content['x-retry-count'] < options.retries) {
57
63
  msg.content['x-retry-count'] = msg.content['x-retry-count'] ? msg.content['x-retry-count'] + 1 : 1;
58
64
  yield this.sendToQueue(queue, msg.content);
59
65
  }
@@ -86,9 +92,6 @@ class RabbitMq {
86
92
  throw new rabbitError_1.default(`error while using ${type} with no name`);
87
93
  }
88
94
  }
89
- static consumeOptions(options) {
90
- return Object.assign({ limit: 1, deadMessageTtl: null }, options);
91
- }
92
95
  getConnection() {
93
96
  return __awaiter(this, void 0, void 0, function* () {
94
97
  return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
@@ -175,18 +178,17 @@ class RabbitMq {
175
178
  }
176
179
  consume(queue, callback, options) {
177
180
  return __awaiter(this, void 0, void 0, function* () {
181
+ const optionsWithDefaults = Object.assign(Object.assign({}, defaultOptions), options);
178
182
  RabbitMq.validateName('queue', queue);
179
- const { limit, deadMessageTtl } = RabbitMq.consumeOptions(options);
183
+ const { limit, deadMessageTtl } = optionsWithDefaults;
180
184
  const channel = yield this.assertChannel();
181
185
  return channel.addSetup((c) => __awaiter(this, void 0, void 0, function* () {
182
186
  yield c.assertQueue(queue);
183
187
  yield c.prefetch(limit, true);
184
188
  return Promise.all([
185
189
  c.consume(queue, (msg) => {
186
- setImmediate(() => {
187
- outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
188
- callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, { messageTtl: deadMessageTtl }));
189
- });
190
+ outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
191
+ callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
190
192
  }),
191
193
  ]);
192
194
  }));
@@ -194,9 +196,10 @@ class RabbitMq {
194
196
  }
195
197
  consumeFromExchange(queue, exchange, callback, options) {
196
198
  return __awaiter(this, void 0, void 0, function* () {
197
- RabbitMq.validateName('queue', queue);
199
+ const optionsWithDefaults = Object.assign(Object.assign({}, defaultOptions), options);
198
200
  RabbitMq.validateName('exchange', exchange);
199
- const { limit, deadMessageTtl } = RabbitMq.consumeOptions(options);
201
+ RabbitMq.validateName('queue', queue);
202
+ const { limit, deadMessageTtl } = optionsWithDefaults;
200
203
  const channel = yield this.assertChannel();
201
204
  return channel.addSetup((c) => __awaiter(this, void 0, void 0, function* () {
202
205
  const assertExchange = yield assertExchangeFanout(c, exchange);
@@ -206,10 +209,8 @@ class RabbitMq {
206
209
  return Promise.all([
207
210
  c.bindQueue(queue, exchange, ''),
208
211
  c.consume(queue, (msg) => {
209
- setImmediate(() => {
210
- outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
211
- callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, { messageTtl: deadMessageTtl }));
212
- });
212
+ outbreak_1.newTrace(outbreak_1.traceTypes.RABBIT);
213
+ callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
213
214
  }),
214
215
  ]);
215
216
  }));
@@ -16,30 +16,48 @@ Object.defineProperty(exports, "__esModule", { value: true });
16
16
  const index_1 = __importDefault(require("./index"));
17
17
  jest.setTimeout(120000);
18
18
  const rabbit = new index_1.default();
19
- const delay = () => new Promise((resolve) => setTimeout(() => resolve(), 500));
19
+ const delay = (ms = 500) => new Promise((resolve) => setTimeout(() => resolve(), ms));
20
+ const callback = (eq = 'hey') => (msg, ack) => {
21
+ expect(msg.content).toEqual(eq);
22
+ ack(msg);
23
+ };
24
+ const nackcallback = () => (msg, ack, nack) => {
25
+ console.log('msg', msg.content);
26
+ expect(msg.content.ttt).toEqual('hey-q');
27
+ nack(msg);
28
+ };
20
29
  describe('RabbitMQ', () => {
21
30
  it('check exchange', () => __awaiter(void 0, void 0, void 0, function* () {
22
- const callback = (msg, ack) => {
23
- expect(msg.content).toEqual('hey');
24
- ack(msg);
25
- };
26
- const mockFn = jest.fn(callback);
31
+ const mockFn = jest.fn(callback());
27
32
  yield rabbit.consumeFromExchange('test-q2', 'test-e', mockFn);
28
33
  yield rabbit.publish('test-e', 'hey');
29
34
  yield delay();
30
35
  expect(mockFn).toBeCalled();
31
36
  }));
32
37
  it('check queue', () => __awaiter(void 0, void 0, void 0, function* () {
33
- const callback = (msg, ack) => {
34
- expect(msg.content).toEqual('hey-q');
35
- ack(msg);
36
- };
37
- const mockFn = jest.fn(callback);
38
+ const mockFn = jest.fn(callback('hey-q'));
38
39
  yield rabbit.consume('test-q-2', mockFn);
39
40
  yield rabbit.sendToQueue('test-q-2', 'hey-q');
40
41
  yield delay();
41
42
  expect(mockFn).toBeCalled();
42
43
  }));
44
+ it('check retry', () => __awaiter(void 0, void 0, void 0, function* () {
45
+ const mockFn = jest.fn(nackcallback());
46
+ yield rabbit.consume('test-q-retry', mockFn, { retries: 3 });
47
+ yield rabbit.sendToQueue('test-q-retry', { ttt: 'hey-q' });
48
+ yield delay(1500);
49
+ expect(mockFn).toHaveBeenCalledTimes(4); // one run then 3 times retry
50
+ }));
51
+ it('check nack and dead queue', () => __awaiter(void 0, void 0, void 0, function* () {
52
+ const mockFn = jest.fn(nackcallback());
53
+ yield rabbit.consume('test-q-nack', mockFn);
54
+ yield rabbit.sendToQueue('test-q-nack', { ttt: 'hey-q' });
55
+ yield delay(1000);
56
+ expect(mockFn).toHaveBeenCalledTimes(2); // one run then 1 time retry
57
+ yield delay();
58
+ const length = yield rabbit.getQueueLength('test-q-nack-dead');
59
+ expect(length.messageCount).toEqual(1);
60
+ }));
43
61
  it('cant publish to unknown exchange', () => __awaiter(void 0, void 0, void 0, function* () {
44
62
  let err;
45
63
  try {
@@ -76,10 +94,7 @@ describe('RabbitMQ', () => {
76
94
  yield rabbit.publish(exchangeName, 'hey');
77
95
  ({ messageCount } = yield rabbit.getQueueLength(queueName));
78
96
  expect(messageCount).toEqual(2);
79
- yield rabbit.consumeFromExchange(queueName, exchangeName, (msg, ack) => __awaiter(void 0, void 0, void 0, function* () {
80
- expect(msg.content).toEqual('hey');
81
- ack(msg);
82
- }));
97
+ yield rabbit.consumeFromExchange(queueName, exchangeName, callback());
83
98
  yield delay();
84
99
  ({ messageCount } = yield rabbit.getQueueLength(queueName));
85
100
  expect(messageCount).toEqual(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/index.test.ts CHANGED
@@ -5,15 +5,22 @@ jest.setTimeout(120000);
5
5
 
6
6
  const rabbit = new RabbitMq();
7
7
 
8
- const delay = () => new Promise((resolve) => setTimeout(() => resolve(), 500));
8
+ const delay = (ms = 500) => new Promise((resolve) => setTimeout(() => resolve(), ms));
9
+
10
+ const callback = (eq = 'hey') => (msg: any, ack: any) => {
11
+ expect(msg.content).toEqual(eq);
12
+ ack(msg);
13
+ };
14
+
15
+ const nackcallback = () => (msg: any, ack: any, nack: any) => {
16
+ console.log('msg', msg.content);
17
+ expect(msg.content.ttt).toEqual('hey-q');
18
+ nack(msg);
19
+ };
9
20
 
10
21
  describe('RabbitMQ', () => {
11
22
  it('check exchange', async () => {
12
- const callback = (msg: any, ack: any) => {
13
- expect(msg.content).toEqual('hey');
14
- ack(msg);
15
- };
16
- const mockFn = jest.fn(callback);
23
+ const mockFn = jest.fn(callback());
17
24
  await rabbit.consumeFromExchange('test-q2', 'test-e', mockFn);
18
25
  await rabbit.publish('test-e', 'hey');
19
26
  await delay();
@@ -21,17 +28,32 @@ describe('RabbitMQ', () => {
21
28
  });
22
29
 
23
30
  it('check queue', async () => {
24
- const callback = (msg: any, ack: any) => {
25
- expect(msg.content).toEqual('hey-q');
26
- ack(msg);
27
- };
28
- const mockFn = jest.fn(callback);
31
+ const mockFn = jest.fn(callback('hey-q'));
29
32
  await rabbit.consume('test-q-2', mockFn);
30
33
  await rabbit.sendToQueue('test-q-2', 'hey-q');
31
34
  await delay();
32
35
  expect(mockFn).toBeCalled();
33
36
  });
34
37
 
38
+ it('check retry', async () => {
39
+ const mockFn = jest.fn(nackcallback());
40
+ await rabbit.consume('test-q-retry', mockFn, { retries: 3 });
41
+ await rabbit.sendToQueue('test-q-retry', { ttt: 'hey-q' });
42
+ await delay(1500);
43
+ expect(mockFn).toHaveBeenCalledTimes(4); // one run then 3 times retry
44
+ });
45
+
46
+ it('check nack and dead queue', async () => {
47
+ const mockFn = jest.fn(nackcallback());
48
+ await rabbit.consume('test-q-nack', mockFn);
49
+ await rabbit.sendToQueue('test-q-nack', { ttt: 'hey-q' });
50
+ await delay(1000);
51
+ expect(mockFn).toHaveBeenCalledTimes(2); // one run then 1 time retry
52
+ await delay();
53
+ const length = await rabbit.getQueueLength('test-q-nack-dead');
54
+ expect(length.messageCount).toEqual(1);
55
+ });
56
+
35
57
  it('cant publish to unknown exchange', async () => {
36
58
  let err;
37
59
  try {
@@ -71,10 +93,7 @@ describe('RabbitMQ', () => {
71
93
  await rabbit.publish(exchangeName, 'hey');
72
94
  ({ messageCount } = await rabbit.getQueueLength(queueName));
73
95
  expect(messageCount).toEqual(2);
74
- await rabbit.consumeFromExchange(queueName, exchangeName, async (msg: any, ack: any) => {
75
- expect(msg.content).toEqual('hey');
76
- ack(msg);
77
- });
96
+ await rabbit.consumeFromExchange(queueName, exchangeName, callback());
78
97
  await delay();
79
98
  ({ messageCount } = await rabbit.getQueueLength(queueName));
80
99
  expect(messageCount).toEqual(0);
package/src/index.ts CHANGED
@@ -15,6 +15,14 @@ export interface AfRabbitOptions {
15
15
  reconnect: boolean
16
16
  }
17
17
 
18
+ const DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 48;
19
+
20
+ const defaultOptions = {
21
+ limit: 1,
22
+ retries: 1,
23
+ deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,
24
+ };
25
+
18
26
  const assertExchangeFanout = (c: any, exchangeName: string) => c.assertExchange(exchangeName, 'fanout');
19
27
 
20
28
  const connectionCreatedConst = 'connectionCreated';
@@ -39,14 +47,6 @@ class RabbitMq {
39
47
  }
40
48
  }
41
49
 
42
- static consumeOptions(options?: any): {limit: number, deadMessageTtl: number} {
43
- return {
44
- limit: 1,
45
- deadMessageTtl: null,
46
- ...options,
47
- };
48
- }
49
-
50
50
  PUBLISH_TIMEOUT = Number(process.env.RABBITMQ_PUBLISH_TIMEOUT) || 60000;
51
51
 
52
52
  PUBLISH_ERROR_MSG = `rabbit: publish timeout(${this.PUBLISH_TIMEOUT}ms) has pass, exchange: `;
@@ -82,9 +82,9 @@ class RabbitMq {
82
82
  }
83
83
  }
84
84
 
85
- public nack = (queue: string, deadQueueOptions?: Options.AssertQueue) => async (msg: any, retries: number) => {
85
+ public nack = (queue: string, options: any, deadQueueOptions: Options.AssertQueue) => async (msg: any) => {
86
86
  if (this.channel) {
87
- if (!msg.content['x-retry-count'] || msg.content['x-retry-count'] <= retries) {
87
+ if (!msg.content['x-retry-count'] || msg.content['x-retry-count'] < options.retries) {
88
88
  msg.content['x-retry-count'] = msg.content['x-retry-count'] ? msg.content['x-retry-count'] + 1 : 1;
89
89
  await this.sendToQueue(queue, msg.content);
90
90
  } else {
@@ -175,8 +175,9 @@ class RabbitMq {
175
175
  }
176
176
 
177
177
  async consume(queue: string, callback: (msg: any, ack: Function, nack: Function) => any, options?: any) {
178
+ const optionsWithDefaults = { ...defaultOptions, ...options };
178
179
  RabbitMq.validateName('queue', queue);
179
- const { limit, deadMessageTtl } = RabbitMq.consumeOptions(options);
180
+ const { limit, deadMessageTtl } = optionsWithDefaults;
180
181
  const channel: ChannelWrapper = await this.assertChannel();
181
182
  return channel.addSetup(async (c: ConfirmChannel) => {
182
183
  await c.assertQueue(queue);
@@ -185,10 +186,8 @@ class RabbitMq {
185
186
  c.consume(
186
187
  queue,
187
188
  (msg: any) => {
188
- setImmediate(() => {
189
- newTrace(traceTypes.RABBIT);
190
- callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, { messageTtl: deadMessageTtl }));
191
- })
189
+ newTrace(traceTypes.RABBIT);
190
+ callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
192
191
  },
193
192
  ),
194
193
  ]);
@@ -196,9 +195,10 @@ class RabbitMq {
196
195
  }
197
196
 
198
197
  async consumeFromExchange(queue: string, exchange: string, callback: (msg: any, ack: Function, nack: Function) => any, options?: any) {
199
- RabbitMq.validateName('queue', queue);
198
+ const optionsWithDefaults = { ...defaultOptions, ...options };
200
199
  RabbitMq.validateName('exchange', exchange);
201
- const { limit, deadMessageTtl } = RabbitMq.consumeOptions(options);
200
+ RabbitMq.validateName('queue', queue);
201
+ const { limit, deadMessageTtl } = optionsWithDefaults;
202
202
  const channel: ChannelWrapper = await this.assertChannel();
203
203
 
204
204
  return channel.addSetup(async (c: ConfirmChannel) => {
@@ -211,10 +211,8 @@ class RabbitMq {
211
211
  c.consume(
212
212
  queue,
213
213
  (msg: any) => {
214
- setImmediate(() => {
215
- newTrace(traceTypes.RABBIT);
216
- callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, { messageTtl: deadMessageTtl }));
217
- })
214
+ newTrace(traceTypes.RABBIT);
215
+ callback(RabbitMq.parseMsg(msg), this.ack, this.nack(queue, optionsWithDefaults, { messageTtl: deadMessageTtl }));
218
216
  },
219
217
  ),
220
218
  ]);