@autofleet/rabbit 3.2.19-beta.7 → 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 -61
- 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 -77
- 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,31 +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
|
-
let { 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
|
-
|
|
166
|
+
this.creatingConnection = true;
|
|
173
167
|
let isResolved = false;
|
|
174
168
|
// It is import to use it as a function and not as a variable
|
|
175
169
|
// because of k8s changes the env variables
|
|
@@ -182,15 +176,11 @@ class RabbitMq {
|
|
|
182
176
|
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
183
177
|
};
|
|
184
178
|
const defaultUrls = findServers();
|
|
185
|
-
const
|
|
179
|
+
const connection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
186
180
|
findServers,
|
|
187
181
|
});
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return resolve(connectionByRole);
|
|
191
|
-
}
|
|
192
|
-
connectionByRole = newConnection;
|
|
193
|
-
connectionByRole.on('error', (err) => {
|
|
182
|
+
this.connection = connection;
|
|
183
|
+
this.connection.on('error', (err) => {
|
|
194
184
|
logger_1.default.error('rabbit: connection error', { err });
|
|
195
185
|
if (!isResolved) {
|
|
196
186
|
isResolved = true;
|
|
@@ -198,7 +188,7 @@ class RabbitMq {
|
|
|
198
188
|
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
199
189
|
}
|
|
200
190
|
});
|
|
201
|
-
|
|
191
|
+
this.connection.on('connectFailed', (err) => {
|
|
202
192
|
this.consumersTags = [];
|
|
203
193
|
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
204
194
|
if (!isResolved) {
|
|
@@ -207,7 +197,8 @@ class RabbitMq {
|
|
|
207
197
|
this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
|
|
208
198
|
}
|
|
209
199
|
});
|
|
210
|
-
|
|
200
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
201
|
+
// this.channel = null;
|
|
211
202
|
this.consumersTags = [];
|
|
212
203
|
debug('rabbit: connection closed');
|
|
213
204
|
if (this.options?.disableReconnect) {
|
|
@@ -218,27 +209,24 @@ class RabbitMq {
|
|
|
218
209
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
219
210
|
}
|
|
220
211
|
});
|
|
221
|
-
|
|
212
|
+
this.connection.once('connect', async () => {
|
|
222
213
|
debug('rabbit: connection established');
|
|
223
|
-
|
|
224
|
-
this.em.emit(consts_1.CONNECTION_CREATED_CONST,
|
|
214
|
+
this.creatingConnection = false;
|
|
215
|
+
this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
225
216
|
isResolved = true;
|
|
226
|
-
resolve(
|
|
217
|
+
resolve(connection);
|
|
227
218
|
});
|
|
228
219
|
});
|
|
229
220
|
}
|
|
230
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
221
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {} } = {}) {
|
|
231
222
|
let connection;
|
|
232
223
|
try {
|
|
233
|
-
connection = await this.getConnection(
|
|
224
|
+
connection = await this.getConnection();
|
|
234
225
|
}
|
|
235
226
|
catch (e) {
|
|
236
227
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
237
228
|
throw e;
|
|
238
229
|
}
|
|
239
|
-
if (!connection) {
|
|
240
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
241
|
-
}
|
|
242
230
|
const channel = connection.createChannel({ ...options });
|
|
243
231
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
244
232
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
@@ -254,14 +242,14 @@ class RabbitMq {
|
|
|
254
242
|
throw err;
|
|
255
243
|
}
|
|
256
244
|
}
|
|
257
|
-
async assertChannel({ force = false
|
|
245
|
+
async assertChannel({ force = false } = {}) {
|
|
258
246
|
if (!this.publishChannelSetupPromise) {
|
|
259
247
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
260
248
|
if (this.channel && !force) {
|
|
261
249
|
return resolve(this.channel);
|
|
262
250
|
}
|
|
263
251
|
try {
|
|
264
|
-
const channel = await this.getNewChannel({
|
|
252
|
+
const channel = await this.getNewChannel({});
|
|
265
253
|
channel.on('error', (err) => {
|
|
266
254
|
logger_1.default.error('rabbit: channel error', { err });
|
|
267
255
|
});
|
|
@@ -276,7 +264,7 @@ class RabbitMq {
|
|
|
276
264
|
return this.publishChannelSetupPromise;
|
|
277
265
|
}
|
|
278
266
|
async assertExchange(exchangeName, options) {
|
|
279
|
-
const channel = await this.assertChannel(
|
|
267
|
+
const channel = await this.assertChannel();
|
|
280
268
|
if (this.exchanges[exchangeName]) {
|
|
281
269
|
return this.exchanges[exchangeName];
|
|
282
270
|
}
|
|
@@ -284,33 +272,32 @@ class RabbitMq {
|
|
|
284
272
|
this.exchanges[exchangeName] = exchange;
|
|
285
273
|
return exchange;
|
|
286
274
|
}
|
|
287
|
-
async getQueueLength(queue
|
|
275
|
+
async getQueueLength(queue) {
|
|
288
276
|
RabbitMq.validateName('queue', queue);
|
|
289
|
-
const { connectionByRole } = this.geConnectionByRole(connectionRole);
|
|
290
277
|
const { channel } = this;
|
|
291
278
|
if (!channel) {
|
|
292
279
|
throw new Error('channel is not defined');
|
|
293
280
|
}
|
|
294
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
281
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
295
282
|
return channel?.checkQueue(queue);
|
|
296
283
|
}
|
|
297
|
-
async deleteQueue(queue
|
|
284
|
+
async deleteQueue(queue) {
|
|
298
285
|
RabbitMq.validateName('queue', queue);
|
|
299
|
-
const channel = await this.assertChannel(
|
|
286
|
+
const channel = await this.assertChannel();
|
|
300
287
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
301
288
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
302
289
|
debug('queue deleted', deleteQueueRes);
|
|
303
290
|
return deleteQueueRes;
|
|
304
291
|
}
|
|
305
|
-
async bindQueue(queue, exchange
|
|
306
|
-
const channel = await this.assertChannel(
|
|
292
|
+
async bindQueue(queue, exchange) {
|
|
293
|
+
const channel = await this.assertChannel();
|
|
307
294
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
308
295
|
return channel.bindQueue(queue, exchange, '');
|
|
309
296
|
}
|
|
310
|
-
async setupQueue(queueName,
|
|
297
|
+
async setupQueue(queueName, options) {
|
|
311
298
|
let queue;
|
|
312
299
|
try {
|
|
313
|
-
const channel = await this.assertChannel(
|
|
300
|
+
const channel = await this.assertChannel();
|
|
314
301
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
315
302
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
|
|
316
303
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -320,8 +307,8 @@ class RabbitMq {
|
|
|
320
307
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
321
308
|
if (!this.options?.dontRetryAssert) {
|
|
322
309
|
debug('retrying assertQueue', { queueName });
|
|
323
|
-
const channel = await this.assertChannel({ force: true
|
|
324
|
-
await this.deleteQueue(queueName
|
|
310
|
+
const channel = await this.assertChannel({ force: true });
|
|
311
|
+
await this.deleteQueue(queueName);
|
|
325
312
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
326
313
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
|
|
327
314
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -334,7 +321,7 @@ class RabbitMq {
|
|
|
334
321
|
this.queues[queueName] = queueName;
|
|
335
322
|
return queue;
|
|
336
323
|
}
|
|
337
|
-
async assertQueue(queueName,
|
|
324
|
+
async assertQueue(queueName, options) {
|
|
338
325
|
RabbitMq.validateName('queue', queueName);
|
|
339
326
|
if (this.queues[queueName]) {
|
|
340
327
|
delete this.queueSetupPromises[queueName];
|
|
@@ -343,7 +330,7 @@ class RabbitMq {
|
|
|
343
330
|
if (this.queueSetupPromises[queueName]) {
|
|
344
331
|
return this.queueSetupPromises[queueName];
|
|
345
332
|
}
|
|
346
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
333
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
347
334
|
return this.queueSetupPromises[queueName];
|
|
348
335
|
}
|
|
349
336
|
saveConsumer(queue, callback, options) {
|
|
@@ -386,7 +373,7 @@ class RabbitMq {
|
|
|
386
373
|
}
|
|
387
374
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
388
375
|
}
|
|
389
|
-
const channel = await this.getNewChannel({
|
|
376
|
+
const channel = await this.getNewChannel({});
|
|
390
377
|
return channel.addSetup(async (confirmChannel) => {
|
|
391
378
|
await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
|
|
392
379
|
await confirmChannel.prefetch(limit, true);
|
|
@@ -466,7 +453,7 @@ class RabbitMq {
|
|
|
466
453
|
RabbitMq.validateName('queue', queue);
|
|
467
454
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
468
455
|
await this.saveConsumer(queue, callback, options);
|
|
469
|
-
const channel = await this.getNewChannel({ name: `consume
|
|
456
|
+
const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
470
457
|
return channel.addSetup(async (c) => {
|
|
471
458
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
472
459
|
await c.assertQueue(queue);
|
|
@@ -481,14 +468,14 @@ class RabbitMq {
|
|
|
481
468
|
async publish(exchange, content, customHeaders) {
|
|
482
469
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
483
470
|
RabbitMq.validateName('exchange', exchange);
|
|
484
|
-
const channel = await this.assertChannel(
|
|
485
|
-
await this.assertExchange(exchange
|
|
471
|
+
const channel = await this.assertChannel();
|
|
472
|
+
await this.assertExchange(exchange);
|
|
486
473
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
487
474
|
});
|
|
488
475
|
}
|
|
489
476
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
490
477
|
try {
|
|
491
|
-
await this.assertChannel(
|
|
478
|
+
await this.assertChannel();
|
|
492
479
|
}
|
|
493
480
|
catch (e) {
|
|
494
481
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -496,7 +483,7 @@ class RabbitMq {
|
|
|
496
483
|
}
|
|
497
484
|
try {
|
|
498
485
|
RabbitMq.validateName('queue', queue);
|
|
499
|
-
await this.assertQueue(queue,
|
|
486
|
+
await this.assertQueue(queue, options);
|
|
500
487
|
}
|
|
501
488
|
catch (e) {
|
|
502
489
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
@@ -508,17 +495,13 @@ class RabbitMq {
|
|
|
508
495
|
return res;
|
|
509
496
|
}
|
|
510
497
|
catch (e) {
|
|
511
|
-
const isConnected = await this.isConnected(
|
|
498
|
+
const isConnected = await this.isConnected();
|
|
512
499
|
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
513
500
|
throw e;
|
|
514
501
|
}
|
|
515
502
|
}
|
|
516
|
-
async isConnected(
|
|
517
|
-
const connection = await this.getConnection(
|
|
518
|
-
if (!connection) {
|
|
519
|
-
logger_1.default.error('rabbit: isConnected - false');
|
|
520
|
-
return false;
|
|
521
|
-
}
|
|
503
|
+
async isConnected() {
|
|
504
|
+
const connection = await this.getConnection();
|
|
522
505
|
const isConnected = connection.isConnected();
|
|
523
506
|
if (!isConnected) {
|
|
524
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,35 +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
|
-
let { 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
|
-
|
|
296
|
+
this.creatingConnection = true;
|
|
310
297
|
let isResolved = false;
|
|
311
298
|
|
|
312
299
|
// It is import to use it as a function and not as a variable
|
|
@@ -323,18 +310,12 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
323
310
|
};
|
|
324
311
|
|
|
325
312
|
const defaultUrls = findServers();
|
|
326
|
-
const
|
|
313
|
+
const connection: AmqpConnectionManager = await connect(defaultUrls, {
|
|
327
314
|
findServers,
|
|
328
315
|
});
|
|
329
316
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return resolve(connectionByRole);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
connectionByRole = newConnection;
|
|
336
|
-
|
|
337
|
-
connectionByRole.on('error', (err) => {
|
|
317
|
+
this.connection = connection;
|
|
318
|
+
this.connection.on('error', (err) => {
|
|
338
319
|
logger.error('rabbit: connection error', { err });
|
|
339
320
|
if (!isResolved) {
|
|
340
321
|
isResolved = true;
|
|
@@ -343,7 +324,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
343
324
|
}
|
|
344
325
|
});
|
|
345
326
|
|
|
346
|
-
|
|
327
|
+
this.connection.on('connectFailed', (err) => {
|
|
347
328
|
this.consumersTags = [];
|
|
348
329
|
logger.error('rabbit: connection connectFailed', { err });
|
|
349
330
|
if (!isResolved) {
|
|
@@ -353,7 +334,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
353
334
|
}
|
|
354
335
|
});
|
|
355
336
|
|
|
356
|
-
|
|
337
|
+
this.connection.on('disconnect', ({ err }) => {
|
|
338
|
+
// this.channel = null;
|
|
357
339
|
this.consumersTags = [];
|
|
358
340
|
debug('rabbit: connection closed');
|
|
359
341
|
if (this.options?.disableReconnect) {
|
|
@@ -363,29 +345,25 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
363
345
|
logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
364
346
|
}
|
|
365
347
|
});
|
|
366
|
-
|
|
348
|
+
|
|
349
|
+
this.connection.once('connect', async () => {
|
|
367
350
|
debug('rabbit: connection established');
|
|
368
|
-
|
|
369
|
-
this.em.emit(CONNECTION_CREATED_CONST,
|
|
351
|
+
this.creatingConnection = false;
|
|
352
|
+
this.em.emit(CONNECTION_CREATED_CONST, connection);
|
|
370
353
|
isResolved = true;
|
|
371
|
-
resolve(
|
|
354
|
+
resolve(connection);
|
|
372
355
|
});
|
|
373
356
|
});
|
|
374
357
|
}
|
|
375
358
|
|
|
376
|
-
async getNewChannel({
|
|
377
|
-
|
|
378
|
-
}: newChannelOpts = { connectionRole: ConnectionRole.Consumer }): Promise<ChannelWrapper> {
|
|
379
|
-
let connection!: AmqpConnectionManager | undefined | null;
|
|
359
|
+
async getNewChannel({ name = rand().toString(), onClose = null, options = {} }: newChannelOpts = {}) {
|
|
360
|
+
let connection!: AmqpConnectionManager;
|
|
380
361
|
try {
|
|
381
|
-
connection = await this.getConnection(
|
|
362
|
+
connection = await this.getConnection();
|
|
382
363
|
} catch (e) {
|
|
383
364
|
logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
384
365
|
throw e;
|
|
385
366
|
}
|
|
386
|
-
if (!connection) {
|
|
387
|
-
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
388
|
-
}
|
|
389
367
|
const channel = connection.createChannel({ ...options });
|
|
390
368
|
once(channel, 'close').then((args) => {
|
|
391
369
|
logger.error(`rabbit: channel ${name} closed`);
|
|
@@ -401,7 +379,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
401
379
|
}
|
|
402
380
|
}
|
|
403
381
|
|
|
404
|
-
async assertChannel({ force = false
|
|
382
|
+
async assertChannel({ force = false } : assertChannelOpts = {}): Promise<ChannelWrapper> {
|
|
405
383
|
if (!this.publishChannelSetupPromise) {
|
|
406
384
|
this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
|
|
407
385
|
if (this.channel && !force) {
|
|
@@ -409,7 +387,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
409
387
|
}
|
|
410
388
|
|
|
411
389
|
try {
|
|
412
|
-
const channel = await this.getNewChannel({
|
|
390
|
+
const channel = await this.getNewChannel({});
|
|
413
391
|
channel.on('error', (err) => {
|
|
414
392
|
logger.error('rabbit: channel error', { err });
|
|
415
393
|
});
|
|
@@ -424,7 +402,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
424
402
|
}
|
|
425
403
|
|
|
426
404
|
async assertExchange(exchangeName: string, options?: any) {
|
|
427
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
405
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
428
406
|
if (this.exchanges[exchangeName]) {
|
|
429
407
|
return this.exchanges[exchangeName];
|
|
430
408
|
}
|
|
@@ -433,36 +411,35 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
433
411
|
return exchange;
|
|
434
412
|
}
|
|
435
413
|
|
|
436
|
-
async getQueueLength(queue: string
|
|
414
|
+
async getQueueLength(queue: string) {
|
|
437
415
|
RabbitMq.validateName('queue', queue);
|
|
438
|
-
const { connectionByRole } = this.geConnectionByRole(connectionRole);
|
|
439
416
|
const { channel } = this;
|
|
440
417
|
if (!channel) {
|
|
441
418
|
throw new Error('channel is not defined');
|
|
442
419
|
}
|
|
443
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
420
|
+
debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
|
|
444
421
|
return channel?.checkQueue(queue);
|
|
445
422
|
}
|
|
446
423
|
|
|
447
|
-
private async deleteQueue(queue: string
|
|
424
|
+
private async deleteQueue(queue: string) {
|
|
448
425
|
RabbitMq.validateName('queue', queue);
|
|
449
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
426
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
450
427
|
logger.info('rabbit: deleting queue', { queue });
|
|
451
428
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
452
429
|
debug('queue deleted', deleteQueueRes);
|
|
453
430
|
return deleteQueueRes;
|
|
454
431
|
}
|
|
455
432
|
|
|
456
|
-
async bindQueue(queue: string, exchange: string
|
|
457
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
433
|
+
async bindQueue(queue: string, exchange: string) {
|
|
434
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
458
435
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
459
436
|
return channel.bindQueue(queue, exchange, '');
|
|
460
437
|
}
|
|
461
438
|
|
|
462
|
-
async setupQueue(queueName: string,
|
|
439
|
+
async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
463
440
|
let queue: Replies.AssertQueue;
|
|
464
441
|
try {
|
|
465
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
442
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
466
443
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
467
444
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
|
|
468
445
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -471,8 +448,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
471
448
|
logger.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
472
449
|
if (!this.options?.dontRetryAssert) {
|
|
473
450
|
debug('retrying assertQueue', { queueName });
|
|
474
|
-
const channel = await this.assertChannel({ force: true
|
|
475
|
-
await this.deleteQueue(queueName
|
|
451
|
+
const channel = await this.assertChannel({ force: true });
|
|
452
|
+
await this.deleteQueue(queueName);
|
|
476
453
|
|
|
477
454
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
478
455
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
|
|
@@ -487,7 +464,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
487
464
|
return queue;
|
|
488
465
|
}
|
|
489
466
|
|
|
490
|
-
async assertQueue(queueName: string,
|
|
467
|
+
async assertQueue(queueName: string, options?: Options.AssertQueue) {
|
|
491
468
|
RabbitMq.validateName('queue', queueName);
|
|
492
469
|
if (this.queues[queueName]) {
|
|
493
470
|
delete this.queueSetupPromises[queueName];
|
|
@@ -498,7 +475,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
498
475
|
return this.queueSetupPromises[queueName];
|
|
499
476
|
}
|
|
500
477
|
|
|
501
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName,
|
|
478
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
502
479
|
return this.queueSetupPromises[queueName];
|
|
503
480
|
}
|
|
504
481
|
|
|
@@ -552,7 +529,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
552
529
|
}
|
|
553
530
|
logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
554
531
|
}
|
|
555
|
-
const channel = await this.getNewChannel({
|
|
532
|
+
const channel = await this.getNewChannel({});
|
|
556
533
|
return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
|
|
557
534
|
await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
|
|
558
535
|
await confirmChannel.prefetch(limit, true);
|
|
@@ -644,7 +621,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
644
621
|
RabbitMq.validateName('queue', queue);
|
|
645
622
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
646
623
|
await this.saveConsumer(queue, callback, options);
|
|
647
|
-
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume
|
|
624
|
+
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
|
|
648
625
|
|
|
649
626
|
return channel.addSetup(async (c: ConfirmChannel) => {
|
|
650
627
|
const assertExchange = await assertExchangeFanout(c, exchange);
|
|
@@ -665,8 +642,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
665
642
|
async publish(exchange: string, content: any, customHeaders?: any) : Promise<boolean> {
|
|
666
643
|
return wrapSetImmediate(async () => {
|
|
667
644
|
RabbitMq.validateName('exchange', exchange);
|
|
668
|
-
const channel: ChannelWrapper = await this.assertChannel(
|
|
669
|
-
await this.assertExchange(exchange
|
|
645
|
+
const channel: ChannelWrapper = await this.assertChannel();
|
|
646
|
+
await this.assertExchange(exchange);
|
|
670
647
|
await channel.publish(exchange, '',
|
|
671
648
|
Buffer.from(JSON.stringify(content)),
|
|
672
649
|
RabbitMq.getPublishOptions(customHeaders));
|
|
@@ -680,7 +657,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
680
657
|
customHeaders?: any,
|
|
681
658
|
): Promise<boolean | undefined> {
|
|
682
659
|
try {
|
|
683
|
-
await this.assertChannel(
|
|
660
|
+
await this.assertChannel();
|
|
684
661
|
} catch (e) {
|
|
685
662
|
logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
686
663
|
throw e;
|
|
@@ -688,7 +665,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
688
665
|
|
|
689
666
|
try {
|
|
690
667
|
RabbitMq.validateName('queue', queue);
|
|
691
|
-
await this.assertQueue(queue,
|
|
668
|
+
await this.assertQueue(queue, options);
|
|
692
669
|
} catch (e) {
|
|
693
670
|
logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
694
671
|
throw e;
|
|
@@ -701,18 +678,14 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
701
678
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
702
679
|
return res;
|
|
703
680
|
} catch (e) {
|
|
704
|
-
const isConnected = await this.isConnected(
|
|
681
|
+
const isConnected = await this.isConnected();
|
|
705
682
|
logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
706
683
|
throw e;
|
|
707
684
|
}
|
|
708
685
|
}
|
|
709
686
|
|
|
710
|
-
async isConnected(
|
|
711
|
-
const connection = await this.getConnection(
|
|
712
|
-
if (!connection) {
|
|
713
|
-
logger.error('rabbit: isConnected - false');
|
|
714
|
-
return false;
|
|
715
|
-
}
|
|
687
|
+
async isConnected() : Promise<boolean> {
|
|
688
|
+
const connection = await this.getConnection();
|
|
716
689
|
const isConnected = connection.isConnected();
|
|
717
690
|
if (!isConnected) {
|
|
718
691
|
logger.error('rabbit: isConnected - false');
|