@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 +4 -3
- package/dist/index.js +49 -35
- package/package.json +1 -1
- package/src/index.ts +59 -41
- package/tsconfig.json +3 -1
- package/.env +0 -0
- package/dump.rdb +0 -0
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) => (
|
|
62
|
-
nack: (channel: ChannelWrapper, queue: string, options: any, deadQueueOptions: Options.AssertQueue) => (
|
|
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<
|
|
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) => (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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) => (
|
|
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.
|
|
67
|
-
|| msg.
|
|
68
|
-
|
|
69
|
-
|
|
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.
|
|
74
|
-
|
|
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
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
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
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 (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
-
|
|
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
|
-
&& (
|
|
175
|
-
|
|
189
|
+
&& (
|
|
190
|
+
!msg.properties.headers[RETRY_HEADER]
|
|
191
|
+
|| parseInt(msg.properties.headers[RETRY_HEADER], 10) < options.retries
|
|
192
|
+
)
|
|
176
193
|
) {
|
|
177
|
-
|
|
178
|
-
|
|
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.
|
|
182
|
-
|
|
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<
|
|
378
|
-
return
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
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
package/.env
DELETED
|
File without changes
|
package/dump.rdb
DELETED
|
Binary file
|