@autofleet/rabbit 3.2.19-beta.8 → 3.2.19
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 +11 -19
- package/dist/index.js +44 -76
- package/dist/lib/types.d.ts +0 -4
- package/dist/lib/types.js +1 -6
- package/package.json +1 -1
- package/src/index.ts +50 -90
- package/src/lib/types.ts +0 -5
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from 'amqp-connection-manager';
|
|
4
4
|
import { ConfirmChannel, ConsumeMessage, Options, Replies } from 'amqplib';
|
|
5
5
|
import { RedisConfig } from './lib/redis';
|
|
6
|
-
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary
|
|
6
|
+
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary } from './lib/types';
|
|
7
7
|
export interface IAfRabbitMq {
|
|
8
8
|
ack: any;
|
|
9
9
|
nack: any;
|
|
@@ -37,12 +37,10 @@ type newChannelOpts = {
|
|
|
37
37
|
name?: string;
|
|
38
38
|
onClose?: null | ((args: any | null) => void);
|
|
39
39
|
options?: CreateChannelOpts | undefined;
|
|
40
|
-
connectionRole: ConnectionRole;
|
|
41
40
|
};
|
|
42
41
|
type assertChannelOpts = {
|
|
43
42
|
channelName?: string;
|
|
44
43
|
force?: boolean;
|
|
45
|
-
connectionRole: ConnectionRole;
|
|
46
44
|
};
|
|
47
45
|
declare class RabbitMq implements IAfRabbitMq {
|
|
48
46
|
static parseMsg(msg: any): any;
|
|
@@ -62,11 +60,9 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
62
60
|
channel: ChannelWrapper | null;
|
|
63
61
|
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
64
62
|
blockReconnect: boolean | null | undefined;
|
|
65
|
-
|
|
66
|
-
publishConnection: AmqpConnectionManager | null | undefined;
|
|
63
|
+
connection: AmqpConnectionManager | null | undefined;
|
|
67
64
|
em: EventEmitter;
|
|
68
|
-
|
|
69
|
-
creatingPublishConnection: boolean;
|
|
65
|
+
creatingConnection: boolean;
|
|
70
66
|
exchanges: ExchangesCache;
|
|
71
67
|
queues: QueuesCache;
|
|
72
68
|
queueSetupPromises: QueueSetupPromisesDictionary;
|
|
@@ -80,19 +76,15 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
80
76
|
private shouldConsumeMessageByTimestamp;
|
|
81
77
|
ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
|
|
82
78
|
nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
87
|
-
getConnection(connectionRole: ConnectionRole): Promise<AmqpConnectionManager | null | undefined>;
|
|
88
|
-
getNewChannel({ name, onClose, options, connectionRole, }?: newChannelOpts): Promise<ChannelWrapper>;
|
|
89
|
-
assertChannel({ force, connectionRole }?: assertChannelOpts): Promise<ChannelWrapper>;
|
|
79
|
+
getConnection(): Promise<AmqpConnectionManager>;
|
|
80
|
+
getNewChannel({ name, onClose, options }?: newChannelOpts): Promise<ChannelWrapper>;
|
|
81
|
+
assertChannel({ force }?: assertChannelOpts): Promise<ChannelWrapper>;
|
|
90
82
|
assertExchange(exchangeName: string, options?: any): Promise<any>;
|
|
91
|
-
getQueueLength(queue: string
|
|
83
|
+
getQueueLength(queue: string): Promise<Replies.AssertQueue>;
|
|
92
84
|
private deleteQueue;
|
|
93
|
-
bindQueue(queue: string, exchange: string
|
|
94
|
-
setupQueue(queueName: string,
|
|
95
|
-
assertQueue(queueName: string,
|
|
85
|
+
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
86
|
+
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
87
|
+
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
|
|
96
88
|
private saveConsumer;
|
|
97
89
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
98
90
|
private lockRedisIfNeeded;
|
|
@@ -101,7 +93,7 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
101
93
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
102
94
|
publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
|
|
103
95
|
sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean | undefined>;
|
|
104
|
-
isConnected(
|
|
96
|
+
isConnected(): Promise<boolean>;
|
|
105
97
|
gracefulShutdown(signal: string): Promise<void>;
|
|
106
98
|
}
|
|
107
99
|
export default RabbitMq;
|
package/dist/index.js
CHANGED
|
@@ -115,16 +115,11 @@ class RabbitMq {
|
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
|
-
this.geConnectionByRole = (connectionRole) => (connectionRole === types_1.ConnectionRole.Consumer
|
|
119
|
-
? { connectionByRole: this.consumeConnection, creatingConnectionByRole: this.creatingConsumeConnection }
|
|
120
|
-
: { connectionByRole: this.publishConnection, creatingConnectionByRole: this.creatingPublishConnection });
|
|
121
118
|
this.em = new events_1.EventEmitter();
|
|
122
119
|
this.channel = null;
|
|
123
120
|
this.publishChannelSetupPromise = null;
|
|
124
|
-
this.
|
|
125
|
-
this.
|
|
126
|
-
this.creatingPublishConnection = false;
|
|
127
|
-
this.creatingConsumeConnection = false;
|
|
121
|
+
this.connection = null;
|
|
122
|
+
this.creatingConnection = false;
|
|
128
123
|
this.exchanges = {};
|
|
129
124
|
this.queues = {};
|
|
130
125
|
this.queueSetupPromises = {};
|
|
@@ -145,36 +140,30 @@ class RabbitMq {
|
|
|
145
140
|
});
|
|
146
141
|
}
|
|
147
142
|
}
|
|
148
|
-
async getConnection(
|
|
143
|
+
async getConnection() {
|
|
149
144
|
return new Promise(async (resolve, reject) => {
|
|
150
|
-
const { connectionByRole, creatingConnectionByRole } = this.geConnectionByRole(connectionRole);
|
|
151
145
|
if (this.blockReconnect) {
|
|
152
146
|
debug('rabbit: block reconnect');
|
|
153
147
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
154
148
|
// @ts-ignore
|
|
155
149
|
return resolve();
|
|
156
150
|
}
|
|
157
|
-
if (
|
|
158
|
-
if (this.options?.disableReconnect ||
|
|
151
|
+
if (this.connection !== null) {
|
|
152
|
+
if (this.options?.disableReconnect || this.connection?.isConnected()) {
|
|
159
153
|
debug('rabbit: connection - is connected');
|
|
160
154
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
161
155
|
// @ts-ignore
|
|
162
|
-
return resolve(
|
|
156
|
+
return resolve(this.connection);
|
|
163
157
|
}
|
|
164
158
|
debug('rabbit: connection - reconnecting');
|
|
165
159
|
}
|
|
166
|
-
if (
|
|
160
|
+
if (this.creatingConnection) {
|
|
167
161
|
debug('rabbit: creating connection emi');
|
|
168
162
|
this.em.once(consts_1.CONNECTION_CREATED_CONST, resolve);
|
|
169
163
|
this.em.once(consts_1.CONNECTION_FAILED_CONST, reject);
|
|
170
164
|
return;
|
|
171
165
|
}
|
|
172
|
-
|
|
173
|
-
this.creatingConsumeConnection = true;
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
this.creatingPublishConnection = true;
|
|
177
|
-
}
|
|
166
|
+
this.creatingConnection = true;
|
|
178
167
|
let isResolved = false;
|
|
179
168
|
// It is import to use it as a function and not as a variable
|
|
180
169
|
// because of k8s changes the env variables
|
|
@@ -187,20 +176,11 @@ class RabbitMq {
|
|
|
187
176
|
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
188
177
|
};
|
|
189
178
|
const defaultUrls = findServers();
|
|
190
|
-
const
|
|
179
|
+
const connection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
191
180
|
findServers,
|
|
192
181
|
});
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return resolve(connectionByRole);
|
|
196
|
-
}
|
|
197
|
-
if (connectionRole === types_1.ConnectionRole.Consumer) {
|
|
198
|
-
this.consumeConnection = newConnection;
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
this.publishConnection = newConnection;
|
|
202
|
-
}
|
|
203
|
-
newConnection.on('error', (err) => {
|
|
182
|
+
this.connection = connection;
|
|
183
|
+
this.connection.on('error', (err) => {
|
|
204
184
|
logger_1.default.error('rabbit: connection error', { err });
|
|
205
185
|
if (!isResolved) {
|
|
206
186
|
isResolved = true;
|
|
@@ -208,7 +188,7 @@ class RabbitMq {
|
|
|
208
188
|
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
209
189
|
}
|
|
210
190
|
});
|
|
211
|
-
|
|
191
|
+
this.connection.on('connectFailed', (err) => {
|
|
212
192
|
this.consumersTags = [];
|
|
213
193
|
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
214
194
|
if (!isResolved) {
|
|
@@ -217,7 +197,8 @@ class RabbitMq {
|
|
|
217
197
|
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
218
198
|
}
|
|
219
199
|
});
|
|
220
|
-
|
|
200
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
201
|
+
// this.channel = null;
|
|
221
202
|
this.consumersTags = [];
|
|
222
203
|
debug('rabbit: connection closed');
|
|
223
204
|
if (this.options?.disableReconnect) {
|
|
@@ -228,32 +209,24 @@ class RabbitMq {
|
|
|
228
209
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
229
210
|
}
|
|
230
211
|
});
|
|
231
|
-
|
|
212
|
+
this.connection.once('connect', async () => {
|
|
232
213
|
debug('rabbit: connection established');
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
else {
|
|
237
|
-
this.creatingPublishConnection = false;
|
|
238
|
-
}
|
|
239
|
-
this.em.emit(consts_1.CONNECTION_CREATED_CONST, newConnection);
|
|
214
|
+
this.creatingConnection = false;
|
|
215
|
+
this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
240
216
|
isResolved = true;
|
|
241
|
-
resolve(
|
|
217
|
+
resolve(connection);
|
|
242
218
|
});
|
|
243
219
|
});
|
|
244
220
|
}
|
|
245
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
221
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {} } = {}) {
|
|
246
222
|
let connection;
|
|
247
223
|
try {
|
|
248
|
-
connection = await this.getConnection(
|
|
224
|
+
connection = await this.getConnection();
|
|
249
225
|
}
|
|
250
226
|
catch (e) {
|
|
251
227
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
252
228
|
throw e;
|
|
253
229
|
}
|
|
254
|
-
if (!connection) {
|
|
255
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
256
|
-
}
|
|
257
230
|
const channel = connection.createChannel({ ...options });
|
|
258
231
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
259
232
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
@@ -269,14 +242,14 @@ class RabbitMq {
|
|
|
269
242
|
throw err;
|
|
270
243
|
}
|
|
271
244
|
}
|
|
272
|
-
async assertChannel({ force = false
|
|
245
|
+
async assertChannel({ force = false } = {}) {
|
|
273
246
|
if (!this.publishChannelSetupPromise) {
|
|
274
247
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
275
248
|
if (this.channel && !force) {
|
|
276
249
|
return resolve(this.channel);
|
|
277
250
|
}
|
|
278
251
|
try {
|
|
279
|
-
const channel = await this.getNewChannel({
|
|
252
|
+
const channel = await this.getNewChannel({});
|
|
280
253
|
channel.on('error', (err) => {
|
|
281
254
|
logger_1.default.error('rabbit: channel error', { err });
|
|
282
255
|
});
|
|
@@ -291,7 +264,7 @@ class RabbitMq {
|
|
|
291
264
|
return this.publishChannelSetupPromise;
|
|
292
265
|
}
|
|
293
266
|
async assertExchange(exchangeName, options) {
|
|
294
|
-
const channel = await this.assertChannel(
|
|
267
|
+
const channel = await this.assertChannel();
|
|
295
268
|
if (this.exchanges[exchangeName]) {
|
|
296
269
|
return this.exchanges[exchangeName];
|
|
297
270
|
}
|
|
@@ -299,33 +272,32 @@ class RabbitMq {
|
|
|
299
272
|
this.exchanges[exchangeName] = exchange;
|
|
300
273
|
return exchange;
|
|
301
274
|
}
|
|
302
|
-
async getQueueLength(queue
|
|
275
|
+
async getQueueLength(queue) {
|
|
303
276
|
RabbitMq.validateName('queue', queue);
|
|
304
|
-
const { connectionByRole } = this.geConnectionByRole(connectionRole);
|
|
305
277
|
const { channel } = this;
|
|
306
278
|
if (!channel) {
|
|
307
279
|
throw new Error('channel is not defined');
|
|
308
280
|
}
|
|
309
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
281
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
310
282
|
return channel?.checkQueue(queue);
|
|
311
283
|
}
|
|
312
|
-
async deleteQueue(queue
|
|
284
|
+
async deleteQueue(queue) {
|
|
313
285
|
RabbitMq.validateName('queue', queue);
|
|
314
|
-
const channel = await this.assertChannel(
|
|
286
|
+
const channel = await this.assertChannel();
|
|
315
287
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
316
288
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
317
289
|
debug('queue deleted', deleteQueueRes);
|
|
318
290
|
return deleteQueueRes;
|
|
319
291
|
}
|
|
320
|
-
async bindQueue(queue, exchange
|
|
321
|
-
const channel = await this.assertChannel(
|
|
292
|
+
async bindQueue(queue, exchange) {
|
|
293
|
+
const channel = await this.assertChannel();
|
|
322
294
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
323
295
|
return channel.bindQueue(queue, exchange, '');
|
|
324
296
|
}
|
|
325
|
-
async setupQueue(queueName,
|
|
297
|
+
async setupQueue(queueName, options) {
|
|
326
298
|
let queue;
|
|
327
299
|
try {
|
|
328
|
-
const channel = await this.assertChannel(
|
|
300
|
+
const channel = await this.assertChannel();
|
|
329
301
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
330
302
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
|
|
331
303
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -335,8 +307,8 @@ class RabbitMq {
|
|
|
335
307
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
336
308
|
if (!this.options?.dontRetryAssert) {
|
|
337
309
|
debug('retrying assertQueue', { queueName });
|
|
338
|
-
const channel = await this.assertChannel({ force: true
|
|
339
|
-
await this.deleteQueue(queueName
|
|
310
|
+
const channel = await this.assertChannel({ force: true });
|
|
311
|
+
await this.deleteQueue(queueName);
|
|
340
312
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
341
313
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
|
|
342
314
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -349,7 +321,7 @@ class RabbitMq {
|
|
|
349
321
|
this.queues[queueName] = queueName;
|
|
350
322
|
return queue;
|
|
351
323
|
}
|
|
352
|
-
async assertQueue(queueName,
|
|
324
|
+
async assertQueue(queueName, options) {
|
|
353
325
|
RabbitMq.validateName('queue', queueName);
|
|
354
326
|
if (this.queues[queueName]) {
|
|
355
327
|
delete this.queueSetupPromises[queueName];
|
|
@@ -358,7 +330,7 @@ class RabbitMq {
|
|
|
358
330
|
if (this.queueSetupPromises[queueName]) {
|
|
359
331
|
return this.queueSetupPromises[queueName];
|
|
360
332
|
}
|
|
361
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
333
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
362
334
|
return this.queueSetupPromises[queueName];
|
|
363
335
|
}
|
|
364
336
|
saveConsumer(queue, callback, options) {
|
|
@@ -401,7 +373,7 @@ class RabbitMq {
|
|
|
401
373
|
}
|
|
402
374
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
403
375
|
}
|
|
404
|
-
const channel = await this.getNewChannel({
|
|
376
|
+
const channel = await this.getNewChannel({});
|
|
405
377
|
return channel.addSetup(async (confirmChannel) => {
|
|
406
378
|
await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
|
|
407
379
|
await confirmChannel.prefetch(limit, true);
|
|
@@ -481,7 +453,7 @@ class RabbitMq {
|
|
|
481
453
|
RabbitMq.validateName('queue', queue);
|
|
482
454
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
483
455
|
await this.saveConsumer(queue, callback, options);
|
|
484
|
-
const channel = await this.getNewChannel({ name: `consume
|
|
456
|
+
const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
485
457
|
return channel.addSetup(async (c) => {
|
|
486
458
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
487
459
|
await c.assertQueue(queue);
|
|
@@ -496,14 +468,14 @@ class RabbitMq {
|
|
|
496
468
|
async publish(exchange, content, customHeaders) {
|
|
497
469
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
498
470
|
RabbitMq.validateName('exchange', exchange);
|
|
499
|
-
const channel = await this.assertChannel(
|
|
500
|
-
await this.assertExchange(exchange
|
|
471
|
+
const channel = await this.assertChannel();
|
|
472
|
+
await this.assertExchange(exchange);
|
|
501
473
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
502
474
|
});
|
|
503
475
|
}
|
|
504
476
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
505
477
|
try {
|
|
506
|
-
await this.assertChannel(
|
|
478
|
+
await this.assertChannel();
|
|
507
479
|
}
|
|
508
480
|
catch (e) {
|
|
509
481
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -511,7 +483,7 @@ class RabbitMq {
|
|
|
511
483
|
}
|
|
512
484
|
try {
|
|
513
485
|
RabbitMq.validateName('queue', queue);
|
|
514
|
-
await this.assertQueue(queue,
|
|
486
|
+
await this.assertQueue(queue, options);
|
|
515
487
|
}
|
|
516
488
|
catch (e) {
|
|
517
489
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
@@ -523,17 +495,13 @@ class RabbitMq {
|
|
|
523
495
|
return res;
|
|
524
496
|
}
|
|
525
497
|
catch (e) {
|
|
526
|
-
const isConnected = await this.isConnected(
|
|
498
|
+
const isConnected = await this.isConnected();
|
|
527
499
|
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
528
500
|
throw e;
|
|
529
501
|
}
|
|
530
502
|
}
|
|
531
|
-
async isConnected(
|
|
532
|
-
const connection = await this.getConnection(
|
|
533
|
-
if (!connection) {
|
|
534
|
-
logger_1.default.error('rabbit: isConnected - false');
|
|
535
|
-
return false;
|
|
536
|
-
}
|
|
503
|
+
async isConnected() {
|
|
504
|
+
const connection = await this.getConnection();
|
|
537
505
|
const isConnected = connection.isConnected();
|
|
538
506
|
if (!isConnected) {
|
|
539
507
|
logger_1.default.error('rabbit: isConnected - false');
|
package/dist/lib/types.d.ts
CHANGED
package/dist/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.CONSUMER_DEFAULT_OPTIONS = void 0;
|
|
4
4
|
const HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';
|
|
5
5
|
const HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';
|
|
6
6
|
exports.CONSUMER_DEFAULT_OPTIONS = {
|
|
@@ -9,8 +9,3 @@ exports.CONSUMER_DEFAULT_OPTIONS = {
|
|
|
9
9
|
[HA_PROMOTE_ON_SHUTDOWN]: 'always',
|
|
10
10
|
},
|
|
11
11
|
};
|
|
12
|
-
var ConnectionRole;
|
|
13
|
-
(function (ConnectionRole) {
|
|
14
|
-
ConnectionRole["Consumer"] = "consumer";
|
|
15
|
-
ConnectionRole["Publisher"] = "publisher";
|
|
16
|
-
})(ConnectionRole = exports.ConnectionRole || (exports.ConnectionRole = {}));
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -36,13 +36,13 @@ import {
|
|
|
36
36
|
QueuesCache,
|
|
37
37
|
RedisLockType,
|
|
38
38
|
ExchangesCache, CONSUMER_DEFAULT_OPTIONS, QueueSetupPromisesDictionary,
|
|
39
|
-
ConnectionRole,
|
|
40
39
|
} from './lib/types';
|
|
41
40
|
|
|
42
41
|
// const debug = nodeDebug('af-rabbitmq')
|
|
43
42
|
const debug = logger.debug.bind(logger);
|
|
44
43
|
|
|
45
44
|
const PUBLISH_TIMEOUT = 1000 * 10;
|
|
45
|
+
|
|
46
46
|
export interface IAfRabbitMq {
|
|
47
47
|
ack: any;
|
|
48
48
|
nack: any;
|
|
@@ -82,13 +82,11 @@ type newChannelOpts = {
|
|
|
82
82
|
name?: string;
|
|
83
83
|
onClose?: null | ((args: any | null) => void);
|
|
84
84
|
options?: CreateChannelOpts | undefined;
|
|
85
|
-
connectionRole: ConnectionRole,
|
|
86
85
|
};
|
|
87
86
|
|
|
88
87
|
type assertChannelOpts = {
|
|
89
88
|
channelName?: string;
|
|
90
89
|
force?: boolean;
|
|
91
|
-
connectionRole: ConnectionRole;
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
type AfConsumer = {
|
|
@@ -147,15 +145,11 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
147
145
|
|
|
148
146
|
blockReconnect: boolean | null | undefined
|
|
149
147
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
publishConnection: AmqpConnectionManager | null | undefined;
|
|
148
|
+
connection: AmqpConnectionManager | null | undefined
|
|
153
149
|
|
|
154
150
|
em: EventEmitter;
|
|
155
151
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
creatingPublishConnection: boolean;
|
|
152
|
+
creatingConnection: boolean;
|
|
159
153
|
|
|
160
154
|
exchanges: ExchangesCache;
|
|
161
155
|
|
|
@@ -178,10 +172,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
178
172
|
this.em = new EventEmitter();
|
|
179
173
|
this.channel = null;
|
|
180
174
|
this.publishChannelSetupPromise = null;
|
|
181
|
-
this.
|
|
182
|
-
this.
|
|
183
|
-
this.creatingPublishConnection = false;
|
|
184
|
-
this.creatingConsumeConnection = false;
|
|
175
|
+
this.connection = null;
|
|
176
|
+
this.creatingConnection = false;
|
|
185
177
|
this.exchanges = {};
|
|
186
178
|
this.queues = {};
|
|
187
179
|
this.queueSetupPromises = {};
|
|
@@ -278,40 +270,30 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
278
270
|
}
|
|
279
271
|
}
|
|
280
272
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
: { connectionByRole: this.publishConnection, creatingConnectionByRole: this.creatingPublishConnection });
|
|
284
|
-
|
|
285
|
-
async getConnection(connectionRole: ConnectionRole) {
|
|
286
|
-
return new Promise<AmqpConnectionManager | undefined | null>(async (resolve, reject) => {
|
|
287
|
-
const { connectionByRole, creatingConnectionByRole } = this.geConnectionByRole(connectionRole);
|
|
273
|
+
async getConnection() {
|
|
274
|
+
return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
|
|
288
275
|
if (this.blockReconnect) {
|
|
289
276
|
debug('rabbit: block reconnect');
|
|
290
277
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
291
278
|
// @ts-ignore
|
|
292
279
|
return resolve();
|
|
293
280
|
}
|
|
294
|
-
if (
|
|
295
|
-
if (this.options?.disableReconnect ||
|
|
281
|
+
if (this.connection !== null) {
|
|
282
|
+
if (this.options?.disableReconnect || this.connection?.isConnected()) {
|
|
296
283
|
debug('rabbit: connection - is connected');
|
|
297
284
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
298
285
|
// @ts-ignore
|
|
299
|
-
return resolve(
|
|
286
|
+
return resolve(this.connection);
|
|
300
287
|
}
|
|
301
288
|
debug('rabbit: connection - reconnecting');
|
|
302
289
|
}
|
|
303
|
-
if (
|
|
290
|
+
if (this.creatingConnection) {
|
|
304
291
|
debug('rabbit: creating connection emi');
|
|
305
292
|
this.em.once(CONNECTION_CREATED_CONST, resolve);
|
|
306
293
|
this.em.once(CONNECTION_FAILED_CONST, reject);
|
|
307
294
|
return;
|
|
308
295
|
}
|
|
309
|
-
|
|
310
|
-
this.creatingConsumeConnection = true;
|
|
311
|
-
} else {
|
|
312
|
-
this.creatingPublishConnection = true;
|
|
313
|
-
}
|
|
314
|
-
|
|
296
|
+
this.creatingConnection = true;
|
|
315
297
|
let isResolved = false;
|
|
316
298
|
|
|
317
299
|
// It is import to use it as a function and not as a variable
|
|
@@ -328,22 +310,12 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
328
310
|
};
|
|
329
311
|
|
|
330
312
|
const defaultUrls = findServers();
|
|
331
|
-
const
|
|
313
|
+
const connection: AmqpConnectionManager = await connect(defaultUrls, {
|
|
332
314
|
findServers,
|
|
333
315
|
});
|
|
334
316
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return resolve(connectionByRole);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (connectionRole === ConnectionRole.Consumer) {
|
|
341
|
-
this.consumeConnection = newConnection;
|
|
342
|
-
} else {
|
|
343
|
-
this.publishConnection = newConnection;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
newConnection.on('error', (err) => {
|
|
317
|
+
this.connection = connection;
|
|
318
|
+
this.connection.on('error', (err) => {
|
|
347
319
|
logger.error('rabbit: connection error', { err });
|
|
348
320
|
if (!isResolved) {
|
|
349
321
|
isResolved = true;
|
|
@@ -352,7 +324,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
352
324
|
}
|
|
353
325
|
});
|
|
354
326
|
|
|
355
|
-
|
|
327
|
+
this.connection.on('connectFailed', (err) => {
|
|
356
328
|
this.consumersTags = [];
|
|
357
329
|
logger.error('rabbit: connection connectFailed', { err });
|
|
358
330
|
if (!isResolved) {
|
|
@@ -362,7 +334,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
362
334
|
}
|
|
363
335
|
});
|
|
364
336
|
|
|
365
|
-
|
|
337
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
338
|
+
// this.channel = null;
|
|
366
339
|
this.consumersTags = [];
|
|
367
340
|
debug('rabbit: connection closed');
|
|
368
341
|
if (this.options?.disableReconnect) {
|
|
@@ -372,33 +345,25 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
372
345
|
logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
373
346
|
}
|
|
374
347
|
});
|
|
375
|
-
|
|
348
|
+
|
|
349
|
+
this.connection.once('connect', async () => {
|
|
376
350
|
debug('rabbit: connection established');
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
} else {
|
|
380
|
-
this.creatingPublishConnection = false;
|
|
381
|
-
}
|
|
382
|
-
this.em.emit(CONNECTION_CREATED_CONST, newConnection);
|
|
351
|
+
this.creatingConnection = false;
|
|
352
|
+
this.em.emit(CONNECTION_CREATED_CONST, connection);
|
|
383
353
|
isResolved = true;
|
|
384
|
-
resolve(
|
|
354
|
+
resolve(connection);
|
|
385
355
|
});
|
|
386
356
|
});
|
|
387
357
|
}
|
|
388
358
|
|
|
389
|
-
async getNewChannel({
|
|
390
|
-
|
|
391
|
-
}: newChannelOpts = { connectionRole: ConnectionRole.Consumer }): Promise<ChannelWrapper> {
|
|
392
|
-
let connection!: AmqpConnectionManager | undefined | null;
|
|
359
|
+
async getNewChannel({ name = rand().toString(), onClose = null, options = {} }: newChannelOpts = {}) {
|
|
360
|
+
let connection!: AmqpConnectionManager;
|
|
393
361
|
try {
|
|
394
|
-
connection = await this.getConnection(
|
|
362
|
+
connection = await this.getConnection();
|
|
395
363
|
} catch (e) {
|
|
396
364
|
logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
397
365
|
throw e;
|
|
398
366
|
}
|
|
399
|
-
if (!connection) {
|
|
400
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
401
|
-
}
|
|
402
367
|
const channel = connection.createChannel({ ...options });
|
|
403
368
|
once(channel, 'close').then((args) => {
|
|
404
369
|
logger.error(`rabbit: channel ${name} closed`);
|
|
@@ -414,7 +379,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
414
379
|
}
|
|
415
380
|
}
|
|
416
381
|
|
|
417
|
-
async assertChannel({ force = false
|
|
382
|
+
async assertChannel({ force = false } : assertChannelOpts = {}): Promise<ChannelWrapper> {
|
|
418
383
|
if (!this.publishChannelSetupPromise) {
|
|
419
384
|
this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
|
|
420
385
|
if (this.channel && !force) {
|
|
@@ -422,7 +387,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
422
387
|
}
|
|
423
388
|
|
|
424
389
|
try {
|
|
425
|
-
const channel = await this.getNewChannel({
|
|
390
|
+
const channel = await this.getNewChannel({});
|
|
426
391
|
channel.on('error', (err) => {
|
|
427
392
|
logger.error('rabbit: channel error', { err });
|
|
428
393
|
});
|
|
@@ -437,7 +402,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
437
402
|
}
|
|
438
403
|
|
|
439
404
|
async assertExchange(exchangeName: string, options?: any) {
|
|
440
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
405
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
441
406
|
if (this.exchanges[exchangeName]) {
|
|
442
407
|
return this.exchanges[exchangeName];
|
|
443
408
|
}
|
|
@@ -446,36 +411,35 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
446
411
|
return exchange;
|
|
447
412
|
}
|
|
448
413
|
|
|
449
|
-
async getQueueLength(queue: string
|
|
414
|
+
async getQueueLength(queue: string) {
|
|
450
415
|
RabbitMq.validateName('queue', queue);
|
|
451
|
-
const { connectionByRole } = this.geConnectionByRole(connectionRole);
|
|
452
416
|
const { channel } = this;
|
|
453
417
|
if (!channel) {
|
|
454
418
|
throw new Error('channel is not defined');
|
|
455
419
|
}
|
|
456
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
420
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
457
421
|
return channel?.checkQueue(queue);
|
|
458
422
|
}
|
|
459
423
|
|
|
460
|
-
private async deleteQueue(queue: string
|
|
424
|
+
private async deleteQueue(queue: string) {
|
|
461
425
|
RabbitMq.validateName('queue', queue);
|
|
462
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
426
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
463
427
|
logger.info('rabbit: deleting queue', { queue });
|
|
464
428
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
465
429
|
debug('queue deleted', deleteQueueRes);
|
|
466
430
|
return deleteQueueRes;
|
|
467
431
|
}
|
|
468
432
|
|
|
469
|
-
async bindQueue(queue: string, exchange: string
|
|
470
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
433
|
+
async bindQueue(queue: string, exchange: string) {
|
|
434
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
471
435
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
472
436
|
return channel.bindQueue(queue, exchange, '');
|
|
473
437
|
}
|
|
474
438
|
|
|
475
|
-
async setupQueue(queueName: string,
|
|
439
|
+
async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
476
440
|
let queue: Replies.AssertQueue;
|
|
477
441
|
try {
|
|
478
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
442
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
479
443
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
480
444
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
|
|
481
445
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -484,8 +448,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
484
448
|
logger.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
485
449
|
if (!this.options?.dontRetryAssert) {
|
|
486
450
|
debug('retrying assertQueue', { queueName });
|
|
487
|
-
const channel = await this.assertChannel({ force: true
|
|
488
|
-
await this.deleteQueue(queueName
|
|
451
|
+
const channel = await this.assertChannel({ force: true });
|
|
452
|
+
await this.deleteQueue(queueName);
|
|
489
453
|
|
|
490
454
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
491
455
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
|
|
@@ -500,7 +464,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
500
464
|
return queue;
|
|
501
465
|
}
|
|
502
466
|
|
|
503
|
-
async assertQueue(queueName: string,
|
|
467
|
+
async assertQueue(queueName: string, options?: Options.AssertQueue) {
|
|
504
468
|
RabbitMq.validateName('queue', queueName);
|
|
505
469
|
if (this.queues[queueName]) {
|
|
506
470
|
delete this.queueSetupPromises[queueName];
|
|
@@ -511,7 +475,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
511
475
|
return this.queueSetupPromises[queueName];
|
|
512
476
|
}
|
|
513
477
|
|
|
514
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
478
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
515
479
|
return this.queueSetupPromises[queueName];
|
|
516
480
|
}
|
|
517
481
|
|
|
@@ -565,7 +529,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
565
529
|
}
|
|
566
530
|
logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
567
531
|
}
|
|
568
|
-
const channel = await this.getNewChannel({
|
|
532
|
+
const channel = await this.getNewChannel({});
|
|
569
533
|
return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
|
|
570
534
|
await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
|
|
571
535
|
await confirmChannel.prefetch(limit, true);
|
|
@@ -657,7 +621,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
657
621
|
RabbitMq.validateName('queue', queue);
|
|
658
622
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
659
623
|
await this.saveConsumer(queue, callback, options);
|
|
660
|
-
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume
|
|
624
|
+
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
661
625
|
|
|
662
626
|
return channel.addSetup(async (c: ConfirmChannel) => {
|
|
663
627
|
const assertExchange = await assertExchangeFanout(c, exchange);
|
|
@@ -678,8 +642,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
678
642
|
async publish(exchange: string, content: any, customHeaders?: any) : Promise<boolean> {
|
|
679
643
|
return wrapSetImmediate(async () => {
|
|
680
644
|
RabbitMq.validateName('exchange', exchange);
|
|
681
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
682
|
-
await this.assertExchange(exchange
|
|
645
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
646
|
+
await this.assertExchange(exchange);
|
|
683
647
|
await channel.publish(exchange, '',
|
|
684
648
|
Buffer.from(JSON.stringify(content)),
|
|
685
649
|
RabbitMq.getPublishOptions(customHeaders));
|
|
@@ -693,7 +657,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
693
657
|
customHeaders?: any,
|
|
694
658
|
): Promise<boolean | undefined> {
|
|
695
659
|
try {
|
|
696
|
-
await this.assertChannel(
|
|
660
|
+
await this.assertChannel();
|
|
697
661
|
} catch (e) {
|
|
698
662
|
logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
699
663
|
throw e;
|
|
@@ -701,7 +665,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
701
665
|
|
|
702
666
|
try {
|
|
703
667
|
RabbitMq.validateName('queue', queue);
|
|
704
|
-
await this.assertQueue(queue,
|
|
668
|
+
await this.assertQueue(queue, options);
|
|
705
669
|
} catch (e) {
|
|
706
670
|
logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
707
671
|
throw e;
|
|
@@ -714,18 +678,14 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
714
678
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
715
679
|
return res;
|
|
716
680
|
} catch (e) {
|
|
717
|
-
const isConnected = await this.isConnected(
|
|
681
|
+
const isConnected = await this.isConnected();
|
|
718
682
|
logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
719
683
|
throw e;
|
|
720
684
|
}
|
|
721
685
|
}
|
|
722
686
|
|
|
723
|
-
async isConnected(
|
|
724
|
-
const connection = await this.getConnection(
|
|
725
|
-
if (!connection) {
|
|
726
|
-
logger.error('rabbit: isConnected - false');
|
|
727
|
-
return false;
|
|
728
|
-
}
|
|
687
|
+
async isConnected() : Promise<boolean> {
|
|
688
|
+
const connection = await this.getConnection();
|
|
729
689
|
const isConnected = connection.isConnected();
|
|
730
690
|
if (!isConnected) {
|
|
731
691
|
logger.error('rabbit: isConnected - false');
|