@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 +5 -3
- package/dist/index.js +35 -27
- package/package.json +1 -1
- package/src/index.ts +47 -34
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:
|
|
73
|
-
nack: (channel:
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 (
|
|
361
|
-
await
|
|
362
|
-
await
|
|
363
|
-
const { consumerTag } = await
|
|
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(
|
|
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(
|
|
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,
|
|
409
|
+
await callback(parsedMessage, localAck, localNack);
|
|
402
410
|
}
|
|
403
411
|
catch (e) {
|
|
404
|
-
await
|
|
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([
|
|
420
|
+
this.consumersTags.push([confirmChannel, consumerTag]);
|
|
413
421
|
}
|
|
414
422
|
});
|
|
415
423
|
}
|
package/package.json
CHANGED
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:
|
|
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:
|
|
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
|
-
}:
|
|
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
|
|
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
|
|
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
|
-
|
|
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 (
|
|
510
|
-
await
|
|
511
|
-
await
|
|
512
|
-
const { consumerTag } = await
|
|
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(
|
|
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(
|
|
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
|
-
|
|
557
|
-
|
|
569
|
+
localAck,
|
|
570
|
+
localNack,
|
|
558
571
|
);
|
|
559
572
|
} catch (e) {
|
|
560
|
-
await
|
|
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([
|
|
581
|
+
this.consumersTags.push([confirmChannel, consumerTag]);
|
|
569
582
|
}
|
|
570
583
|
});
|
|
571
584
|
}
|