@autofleet/rabbit 3.2.25-beta.103 → 3.2.26-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 +28 -14
- package/dist/index.js +108 -85
- package/dist/lib/consts.d.ts +4 -2
- package/dist/lib/consts.js +6 -3
- package/dist/lib/types.d.ts +7 -7
- package/package.json +1 -3
- package/src/index.ts +149 -110
- package/src/lib/consts.ts +5 -2
- package/src/lib/types.ts +8 -9
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
|
|
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 {
|
|
6
|
+
import { ConnectionPurpose } from './lib/consts';
|
|
7
|
+
import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary, ConnectionData } from './lib/types';
|
|
7
8
|
export interface IAfRabbitMq {
|
|
8
9
|
ack: any;
|
|
9
10
|
nack: any;
|
|
@@ -33,6 +34,17 @@ export interface AfRabbitOptions {
|
|
|
33
34
|
dontRetryAssert?: boolean;
|
|
34
35
|
rabbitHost?: string;
|
|
35
36
|
}
|
|
37
|
+
type newChannelOpts = {
|
|
38
|
+
name?: string;
|
|
39
|
+
onClose?: null | ((args: any | null) => void);
|
|
40
|
+
options?: CreateChannelOpts | undefined;
|
|
41
|
+
connectionPurpose?: ConnectionPurpose;
|
|
42
|
+
};
|
|
43
|
+
type assertChannelOpts = {
|
|
44
|
+
channelName?: string;
|
|
45
|
+
force?: boolean;
|
|
46
|
+
connectionPurpose?: ConnectionPurpose;
|
|
47
|
+
};
|
|
36
48
|
declare class RabbitMq implements IAfRabbitMq {
|
|
37
49
|
static parseMsg(msg: any): any;
|
|
38
50
|
static validateName(type: string, name: string): void;
|
|
@@ -48,12 +60,14 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
48
60
|
};
|
|
49
61
|
DISCONNECT_MSG: string;
|
|
50
62
|
RECONNECT_MSG: string;
|
|
51
|
-
|
|
63
|
+
publishChannel: ChannelWrapper | null;
|
|
52
64
|
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
53
65
|
blockReconnect: boolean | null | undefined;
|
|
54
|
-
|
|
66
|
+
connectionsMap: {
|
|
67
|
+
[ConnectionPurpose.Consume]: ConnectionData;
|
|
68
|
+
[ConnectionPurpose.Publish]: ConnectionData;
|
|
69
|
+
};
|
|
55
70
|
em: EventEmitter;
|
|
56
|
-
creatingConnection: boolean;
|
|
57
71
|
exchanges: ExchangesCache;
|
|
58
72
|
queues: QueuesCache;
|
|
59
73
|
queueSetupPromises: QueueSetupPromisesDictionary;
|
|
@@ -68,23 +82,23 @@ declare class RabbitMq implements IAfRabbitMq {
|
|
|
68
82
|
private shouldConsumeMessageByTimestamp;
|
|
69
83
|
ack: (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: null) => (userMsg: ConsumeMessage) => Promise<any>;
|
|
70
84
|
nack: (channel: ConfirmChannel, queue: string, options: any, deadQueueOptions: Options.AssertQueue, msg: ConsumeMessageOrNull, releaseLock: any) => (userMsg: ConsumeMessageOrNull, { skipRetry, }?: NackOptions) => Promise<any>;
|
|
71
|
-
getConnection(): Promise<AmqpConnectionManager>;
|
|
72
|
-
getNewChannel({ name, onClose, options }
|
|
73
|
-
assertChannel({ force,
|
|
74
|
-
assertExchange(exchangeName: string): Promise<any>;
|
|
75
|
-
getQueueLength(queue: string): Promise<Replies.AssertQueue>;
|
|
85
|
+
getConnection(connectionPurpose: ConnectionPurpose): Promise<AmqpConnectionManager | null | undefined>;
|
|
86
|
+
getNewChannel({ name, onClose, options, connectionPurpose, }: newChannelOpts): Promise<ChannelWrapper>;
|
|
87
|
+
assertChannel({ force, connectionPurpose }: assertChannelOpts): Promise<ChannelWrapper>;
|
|
88
|
+
assertExchange(exchangeName: string, options?: any): Promise<any>;
|
|
89
|
+
getQueueLength(queue: string, connectionPurpose?: ConnectionPurpose): Promise<Replies.AssertQueue>;
|
|
76
90
|
private deleteQueue;
|
|
77
|
-
bindQueue(queue: string, exchange: string): Promise<void>;
|
|
78
|
-
setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
91
|
+
bindQueue(queue: string, exchange: string, connectionPurpose: ConnectionPurpose): Promise<void>;
|
|
92
|
+
setupQueue(queueName: string, connectionPurpose: ConnectionPurpose, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
|
|
79
93
|
static shouldUseQuorum(queueName: string): boolean;
|
|
80
|
-
assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
|
|
94
|
+
assertQueue(queueName: string, connectionPurpose: ConnectionPurpose, options?: Options.AssertQueue): Promise<any>;
|
|
81
95
|
private saveConsumer;
|
|
82
96
|
consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
83
97
|
private lockRedisIfNeeded;
|
|
84
98
|
private unlockRedisIfNeeded;
|
|
85
99
|
private consumeFromRabbit;
|
|
86
100
|
consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
|
|
87
|
-
publish(exchange: string, content: any, customHeaders?: any
|
|
101
|
+
publish(exchange: string, content: any, customHeaders?: any): Promise<boolean>;
|
|
88
102
|
sendToQueue(queue: string, content: any, options?: any, customHeaders?: any): Promise<boolean | undefined>;
|
|
89
103
|
isConnected(): Promise<boolean>;
|
|
90
104
|
gracefulShutdown(signal: string): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.sendCeleryTaskViaHttp = void 0;
|
|
8
8
|
const events_1 = require("events");
|
|
9
9
|
const util_1 = require("util");
|
|
10
|
-
const lodash_1 = require("lodash");
|
|
11
10
|
const moment_1 = __importDefault(require("moment"));
|
|
12
11
|
const redis_lock_1 = __importDefault(require("redis-lock"));
|
|
13
12
|
const amqp_connection_manager_1 = require("amqp-connection-manager");
|
|
@@ -118,10 +117,22 @@ class RabbitMq {
|
|
|
118
117
|
}
|
|
119
118
|
};
|
|
120
119
|
this.em = new events_1.EventEmitter();
|
|
121
|
-
this.
|
|
120
|
+
this.publishChannel = null;
|
|
122
121
|
this.publishChannelSetupPromise = null;
|
|
123
|
-
this.
|
|
124
|
-
|
|
122
|
+
this.connectionsMap = {
|
|
123
|
+
[consts_1.ConnectionPurpose.Consume]: {
|
|
124
|
+
connection: null,
|
|
125
|
+
creatingConnection: false,
|
|
126
|
+
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
127
|
+
connectionFailedEventName: 'consumeConnectionFailed',
|
|
128
|
+
},
|
|
129
|
+
[consts_1.ConnectionPurpose.Publish]: {
|
|
130
|
+
connection: null,
|
|
131
|
+
creatingConnection: false,
|
|
132
|
+
connectionCreatedEventName: 'publishConnectionCreated',
|
|
133
|
+
connectionFailedEventName: 'publishConnectionFailed',
|
|
134
|
+
},
|
|
135
|
+
};
|
|
125
136
|
this.exchanges = {};
|
|
126
137
|
this.queues = {};
|
|
127
138
|
this.queueSetupPromises = {};
|
|
@@ -143,30 +154,31 @@ class RabbitMq {
|
|
|
143
154
|
});
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
|
-
async getConnection() {
|
|
157
|
+
async getConnection(connectionPurpose) {
|
|
147
158
|
return new Promise(async (resolve, reject) => {
|
|
159
|
+
const { connection, creatingConnection, connectionCreatedEventName, connectionFailedEventName, } = this.connectionsMap[connectionPurpose];
|
|
148
160
|
if (this.blockReconnect) {
|
|
149
161
|
debug('rabbit: block reconnect');
|
|
150
162
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
151
163
|
// @ts-ignore
|
|
152
164
|
return resolve();
|
|
153
165
|
}
|
|
154
|
-
if (
|
|
155
|
-
if (this.options?.disableReconnect ||
|
|
166
|
+
if (connection !== null) {
|
|
167
|
+
if (this.options?.disableReconnect || connection?.isConnected()) {
|
|
156
168
|
debug('rabbit: connection - is connected');
|
|
157
169
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
158
170
|
// @ts-ignore
|
|
159
|
-
return resolve(
|
|
171
|
+
return resolve(connection);
|
|
160
172
|
}
|
|
161
173
|
debug('rabbit: connection - reconnecting');
|
|
162
174
|
}
|
|
163
|
-
if (
|
|
175
|
+
if (creatingConnection) {
|
|
164
176
|
debug('rabbit: creating connection emi');
|
|
165
|
-
this.em.once(
|
|
166
|
-
this.em.once(
|
|
177
|
+
this.em.once(connectionCreatedEventName, resolve);
|
|
178
|
+
this.em.once(connectionFailedEventName, reject);
|
|
167
179
|
return;
|
|
168
180
|
}
|
|
169
|
-
this.creatingConnection = true;
|
|
181
|
+
this.connectionsMap[connectionPurpose].creatingConnection = true;
|
|
170
182
|
let isResolved = false;
|
|
171
183
|
// It is import to use it as a function and not as a variable
|
|
172
184
|
// because of k8s changes the env variables
|
|
@@ -179,29 +191,29 @@ class RabbitMq {
|
|
|
179
191
|
return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
|
|
180
192
|
};
|
|
181
193
|
const defaultUrls = findServers();
|
|
182
|
-
const
|
|
194
|
+
const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
|
|
183
195
|
findServers,
|
|
184
196
|
});
|
|
185
|
-
this.connection =
|
|
186
|
-
|
|
197
|
+
this.connectionsMap[connectionPurpose].connection = newConnection;
|
|
198
|
+
logger_1.default.info(`rabbit: created new connection ${connectionPurpose}`);
|
|
199
|
+
newConnection.on('error', (err) => {
|
|
187
200
|
logger_1.default.error('rabbit: connection error', { err });
|
|
188
201
|
if (!isResolved) {
|
|
189
202
|
isResolved = true;
|
|
190
203
|
reject(err);
|
|
191
|
-
this.em.emit(
|
|
204
|
+
this.em.emit(connectionFailedEventName, err);
|
|
192
205
|
}
|
|
193
206
|
});
|
|
194
|
-
|
|
207
|
+
newConnection.on('connectFailed', (err) => {
|
|
195
208
|
this.consumersTags = [];
|
|
196
209
|
logger_1.default.error('rabbit: connection connectFailed', { err });
|
|
197
210
|
if (!isResolved) {
|
|
198
211
|
isResolved = true;
|
|
199
212
|
reject(err);
|
|
200
|
-
this.em.emit(
|
|
213
|
+
this.em.emit(connectionFailedEventName, err);
|
|
201
214
|
}
|
|
202
215
|
});
|
|
203
|
-
|
|
204
|
-
// this.channel = null;
|
|
216
|
+
newConnection.on('disconnect', ({ err }) => {
|
|
205
217
|
this.consumersTags = [];
|
|
206
218
|
debug('rabbit: connection closed');
|
|
207
219
|
if (this.options?.disableReconnect) {
|
|
@@ -212,25 +224,27 @@ class RabbitMq {
|
|
|
212
224
|
logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
213
225
|
}
|
|
214
226
|
});
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
this.
|
|
218
|
-
this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
|
|
227
|
+
newConnection.once('connect', async () => {
|
|
228
|
+
this.connectionsMap[connectionPurpose].creatingConnection = false;
|
|
229
|
+
this.em.emit(connectionCreatedEventName, newConnection);
|
|
219
230
|
isResolved = true;
|
|
220
|
-
resolve(
|
|
231
|
+
resolve(newConnection);
|
|
221
232
|
});
|
|
222
233
|
});
|
|
223
234
|
}
|
|
224
|
-
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}
|
|
235
|
+
async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connectionPurpose = consts_1.ConnectionPurpose.Consume, }) {
|
|
225
236
|
let connection;
|
|
226
237
|
try {
|
|
227
|
-
connection = await this.getConnection();
|
|
238
|
+
connection = await this.getConnection(connectionPurpose);
|
|
228
239
|
}
|
|
229
240
|
catch (e) {
|
|
230
241
|
logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
231
242
|
throw e;
|
|
232
243
|
}
|
|
233
|
-
|
|
244
|
+
if (!connection) {
|
|
245
|
+
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
246
|
+
}
|
|
247
|
+
const channel = connection.createChannel({ ...options });
|
|
234
248
|
(0, events_1.once)(channel, 'close').then((args) => {
|
|
235
249
|
logger_1.default.error(`rabbit: channel ${name} closed`);
|
|
236
250
|
onClose?.(args);
|
|
@@ -245,18 +259,20 @@ class RabbitMq {
|
|
|
245
259
|
throw err;
|
|
246
260
|
}
|
|
247
261
|
}
|
|
248
|
-
async assertChannel({ force = false,
|
|
262
|
+
async assertChannel({ force = false, connectionPurpose = consts_1.ConnectionPurpose.Consume }) {
|
|
263
|
+
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
|
|
249
264
|
if (!this.publishChannelSetupPromise) {
|
|
250
265
|
this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
|
|
251
|
-
if (this.
|
|
252
|
-
return resolve(this.
|
|
266
|
+
if (this.publishChannel && !force) {
|
|
267
|
+
return resolve(this.publishChannel);
|
|
253
268
|
}
|
|
254
269
|
try {
|
|
255
|
-
const channel = await this.getNewChannel({
|
|
270
|
+
const channel = await this.getNewChannel({ connectionPurpose });
|
|
271
|
+
debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
|
|
256
272
|
channel.on('error', (err) => {
|
|
257
273
|
logger_1.default.error('rabbit: channel error', { err });
|
|
258
274
|
});
|
|
259
|
-
this.
|
|
275
|
+
this.publishChannel = channel;
|
|
260
276
|
resolve(channel);
|
|
261
277
|
}
|
|
262
278
|
catch (e) {
|
|
@@ -266,8 +282,8 @@ class RabbitMq {
|
|
|
266
282
|
}
|
|
267
283
|
return this.publishChannelSetupPromise;
|
|
268
284
|
}
|
|
269
|
-
async assertExchange(exchangeName) {
|
|
270
|
-
const channel = await this.assertChannel();
|
|
285
|
+
async assertExchange(exchangeName, options = { connectionPurpose: consts_1.ConnectionPurpose.Consume }) {
|
|
286
|
+
const channel = await this.assertChannel({ connectionPurpose: options.connectionPurpose });
|
|
271
287
|
if (this.exchanges[exchangeName]) {
|
|
272
288
|
delete this.assertExchangePromises[exchangeName];
|
|
273
289
|
return this.exchanges[exchangeName];
|
|
@@ -279,29 +295,30 @@ class RabbitMq {
|
|
|
279
295
|
this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];
|
|
280
296
|
return this.exchanges[exchangeName];
|
|
281
297
|
}
|
|
282
|
-
async getQueueLength(queue) {
|
|
298
|
+
async getQueueLength(queue, connectionPurpose = consts_1.ConnectionPurpose.Consume) {
|
|
283
299
|
RabbitMq.validateName('queue', queue);
|
|
284
|
-
const {
|
|
285
|
-
|
|
300
|
+
const { connection } = this.connectionsMap[connectionPurpose];
|
|
301
|
+
const { publishChannel } = this;
|
|
302
|
+
if (!publishChannel) {
|
|
286
303
|
throw new Error('channel is not defined');
|
|
287
304
|
}
|
|
288
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
289
|
-
return
|
|
305
|
+
debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
|
|
306
|
+
return publishChannel?.checkQueue(queue);
|
|
290
307
|
}
|
|
291
|
-
async deleteQueue(queue) {
|
|
308
|
+
async deleteQueue(queue, connectionPurpose) {
|
|
292
309
|
RabbitMq.validateName('queue', queue);
|
|
293
|
-
const channel = await this.assertChannel();
|
|
310
|
+
const channel = await this.assertChannel({ connectionPurpose });
|
|
294
311
|
logger_1.default.info('rabbit: deleting queue', { queue });
|
|
295
312
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
296
313
|
debug('queue deleted', deleteQueueRes);
|
|
297
314
|
return deleteQueueRes;
|
|
298
315
|
}
|
|
299
|
-
async bindQueue(queue, exchange) {
|
|
300
|
-
const channel = await this.assertChannel();
|
|
316
|
+
async bindQueue(queue, exchange, connectionPurpose) {
|
|
317
|
+
const channel = await this.assertChannel({ connectionPurpose });
|
|
301
318
|
await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
302
319
|
return channel.bindQueue(queue, exchange, '');
|
|
303
320
|
}
|
|
304
|
-
async setupQueue(queueName, options) {
|
|
321
|
+
async setupQueue(queueName, connectionPurpose, options) {
|
|
305
322
|
let queue;
|
|
306
323
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
307
324
|
const localeOptions = {
|
|
@@ -314,7 +331,7 @@ class RabbitMq {
|
|
|
314
331
|
},
|
|
315
332
|
};
|
|
316
333
|
try {
|
|
317
|
-
const channel = await this.assertChannel();
|
|
334
|
+
const channel = await this.assertChannel({ connectionPurpose });
|
|
318
335
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
319
336
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
320
337
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -324,8 +341,8 @@ class RabbitMq {
|
|
|
324
341
|
logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
325
342
|
if (!this.options?.dontRetryAssert) {
|
|
326
343
|
debug('retrying assertQueue', { queueName });
|
|
327
|
-
const channel = await this.assertChannel({ force: true });
|
|
328
|
-
await this.deleteQueue(queueName);
|
|
344
|
+
const channel = await this.assertChannel({ force: true, connectionPurpose });
|
|
345
|
+
await this.deleteQueue(queueName, connectionPurpose);
|
|
329
346
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
330
347
|
await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
331
348
|
debug('retrying assertQueue->channel.assertQueue', { queueName });
|
|
@@ -349,7 +366,8 @@ class RabbitMq {
|
|
|
349
366
|
}
|
|
350
367
|
return false;
|
|
351
368
|
}
|
|
352
|
-
async assertQueue(queueName, options) {
|
|
369
|
+
async assertQueue(queueName, connectionPurpose, options) {
|
|
370
|
+
debug('rabbit: start assert queue', { connectionPurpose, queueName });
|
|
353
371
|
RabbitMq.validateName('queue', queueName);
|
|
354
372
|
if (this.queues[queueName]) {
|
|
355
373
|
delete this.queueSetupPromises[queueName];
|
|
@@ -358,7 +376,8 @@ class RabbitMq {
|
|
|
358
376
|
if (this.queueSetupPromises[queueName]) {
|
|
359
377
|
return this.queueSetupPromises[queueName];
|
|
360
378
|
}
|
|
361
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
379
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, connectionPurpose, options);
|
|
380
|
+
debug('rabbit: done assert queue', { connectionPurpose, queueName });
|
|
362
381
|
return this.queueSetupPromises[queueName];
|
|
363
382
|
}
|
|
364
383
|
saveConsumer(queue, callback, options) {
|
|
@@ -401,13 +420,10 @@ class RabbitMq {
|
|
|
401
420
|
}
|
|
402
421
|
logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
403
422
|
}
|
|
404
|
-
const channel = await this.getNewChannel({});
|
|
423
|
+
const channel = await this.getNewChannel({ connectionPurpose: consts_1.ConnectionPurpose.Consume });
|
|
405
424
|
return channel.addSetup(async (confirmChannel) => {
|
|
406
|
-
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
425
|
+
const q = await this.assertQueue(queue, consts_1.ConnectionPurpose.Consume, optionsWithDefaults);
|
|
407
426
|
await confirmChannel.prefetch(limit, false);
|
|
408
|
-
const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
|
|
409
|
-
? (0, lodash_1.merge)(types_1.CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
|
|
410
|
-
: types_1.CONSUMER_DEFAULT_OPTIONS;
|
|
411
427
|
const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
|
|
412
428
|
if (!msg) {
|
|
413
429
|
return null;
|
|
@@ -472,7 +488,7 @@ class RabbitMq {
|
|
|
472
488
|
catch (e) {
|
|
473
489
|
await localNack(msg);
|
|
474
490
|
}
|
|
475
|
-
},
|
|
491
|
+
}, types_1.CONSUMER_DEFAULT_OPTIONS);
|
|
476
492
|
if (!consumerTag) {
|
|
477
493
|
logger_1.default.error(`rabbit: failed to consume from queue ${queue}`);
|
|
478
494
|
}
|
|
@@ -488,29 +504,30 @@ class RabbitMq {
|
|
|
488
504
|
RabbitMq.validateName('queue', queue);
|
|
489
505
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
490
506
|
await this.saveConsumer(queue, callback, options);
|
|
491
|
-
const channel = await this.getNewChannel({ name: `consume-exchange
|
|
507
|
+
const channel = await this.getNewChannel({ name: `consume - exchange - ${exchange} -queue - ${queue}` });
|
|
492
508
|
return channel.addSetup(async (c) => {
|
|
493
509
|
const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
|
|
494
510
|
await c.assertQueue(queue);
|
|
495
511
|
this.exchanges[exchange] = assertExchange;
|
|
496
|
-
await c.prefetch(limit,
|
|
512
|
+
await c.prefetch(limit, true);
|
|
497
513
|
return Promise.all([
|
|
498
514
|
c.bindQueue(queue, exchange, ''),
|
|
499
515
|
this.consume(queue, callback, options),
|
|
500
516
|
]);
|
|
501
517
|
});
|
|
502
518
|
}
|
|
503
|
-
async publish(exchange, content, customHeaders
|
|
519
|
+
async publish(exchange, content, customHeaders) {
|
|
520
|
+
debug('rabbit: start publish msg');
|
|
504
521
|
return (0, utils_1.wrapSetImmediate)(async () => {
|
|
505
522
|
RabbitMq.validateName('exchange', exchange);
|
|
506
|
-
const channel = await this.assertChannel({
|
|
507
|
-
await this.assertExchange(exchange);
|
|
523
|
+
const channel = await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
524
|
+
await this.assertExchange(exchange, { connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
508
525
|
await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
509
526
|
});
|
|
510
527
|
}
|
|
511
528
|
async sendToQueue(queue, content, options, customHeaders) {
|
|
512
529
|
try {
|
|
513
|
-
await this.assertChannel({
|
|
530
|
+
await this.assertChannel({ connectionPurpose: consts_1.ConnectionPurpose.Publish });
|
|
514
531
|
}
|
|
515
532
|
catch (e) {
|
|
516
533
|
logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
@@ -518,43 +535,49 @@ class RabbitMq {
|
|
|
518
535
|
}
|
|
519
536
|
try {
|
|
520
537
|
RabbitMq.validateName('queue', queue);
|
|
521
|
-
await this.assertQueue(queue, options);
|
|
538
|
+
await this.assertQueue(queue, consts_1.ConnectionPurpose.Publish, options);
|
|
522
539
|
}
|
|
523
540
|
catch (e) {
|
|
524
541
|
logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
525
542
|
throw e;
|
|
526
543
|
}
|
|
527
544
|
try {
|
|
528
|
-
const res = await this.
|
|
545
|
+
const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
|
|
529
546
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
530
547
|
return res;
|
|
531
548
|
}
|
|
532
549
|
catch (e) {
|
|
533
|
-
|
|
534
|
-
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
550
|
+
logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}`, { e });
|
|
535
551
|
throw e;
|
|
536
552
|
}
|
|
537
553
|
}
|
|
538
554
|
async isConnected() {
|
|
539
|
-
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
555
|
+
debug('rabbit: start is connected');
|
|
556
|
+
const isEachConnectionConnected = await Promise.all(Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
|
|
557
|
+
const { connection } = connectionData;
|
|
558
|
+
debug('rabbit: is connected inside map', { connection, connectionPurpose });
|
|
559
|
+
const isConnected = connection?.isConnected();
|
|
560
|
+
if (!isConnected) {
|
|
561
|
+
logger_1.default.error('rabbit: isConnected - false', { connectionPurpose });
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
if (connectionPurpose === consts_1.ConnectionPurpose.Publish) {
|
|
565
|
+
const channel = await this.assertChannel({ connectionPurpose: connectionPurpose });
|
|
566
|
+
try {
|
|
567
|
+
await Promise.all([
|
|
568
|
+
channel.waitForConnect(),
|
|
569
|
+
...this.consumers.map((c) => channel.checkQueue(c.queue)),
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
catch (e) {
|
|
573
|
+
logger_1.default.error('rabbit: isConnected - false');
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
logger_1.default.info('rabbit: isConnected - true');
|
|
578
|
+
return true;
|
|
579
|
+
}));
|
|
580
|
+
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
|
558
581
|
}
|
|
559
582
|
async gracefulShutdown(signal) {
|
|
560
583
|
const tagsNumber = this.consumersTags.length;
|
package/dist/lib/consts.d.ts
CHANGED
|
@@ -6,8 +6,6 @@ export declare const USER_TRACING_HEADER = "x-af-user-id";
|
|
|
6
6
|
export declare const AUTOMATION_ID_HEADER = "x-af-automation-id";
|
|
7
7
|
export declare const USER_OBJECT = "userObject";
|
|
8
8
|
export declare const DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
9
|
-
export declare const CONNECTION_CREATED_CONST = "connectionCreated";
|
|
10
|
-
export declare const CONNECTION_FAILED_CONST = "connectionFailed";
|
|
11
9
|
export declare const DEFAULT_OPTIONS: {
|
|
12
10
|
limit: number;
|
|
13
11
|
retries: number;
|
|
@@ -17,3 +15,7 @@ export declare const DEFAULT_OPTIONS: {
|
|
|
17
15
|
auditContext: null;
|
|
18
16
|
enableRabbitTrace: boolean;
|
|
19
17
|
};
|
|
18
|
+
export declare enum ConnectionPurpose {
|
|
19
|
+
Consume = "consume",
|
|
20
|
+
Publish = "publish"
|
|
21
|
+
}
|
package/dist/lib/consts.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ConnectionPurpose = exports.DEFAULT_OPTIONS = exports.DEFAULT_USE_CONSUME_WITH_LOCK = exports.USER_OBJECT = exports.AUTOMATION_ID_HEADER = exports.USER_TRACING_HEADER = exports.TRACING_HEADER = exports.RETRY_HEADER = exports.DEFAULT_LOCK_TIMEOUT = exports.DEFAULT_DEAD_TTL_TWO_DAYS = void 0;
|
|
4
4
|
exports.DEFAULT_DEAD_TTL_TWO_DAYS = 60000 * 60 * 12;
|
|
5
5
|
exports.DEFAULT_LOCK_TIMEOUT = 1000 * 5;
|
|
6
6
|
exports.RETRY_HEADER = 'x-retry-count';
|
|
@@ -9,8 +9,6 @@ exports.USER_TRACING_HEADER = 'x-af-user-id';
|
|
|
9
9
|
exports.AUTOMATION_ID_HEADER = 'x-af-automation-id';
|
|
10
10
|
exports.USER_OBJECT = 'userObject';
|
|
11
11
|
exports.DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
12
|
-
exports.CONNECTION_CREATED_CONST = 'connectionCreated';
|
|
13
|
-
exports.CONNECTION_FAILED_CONST = 'connectionFailed';
|
|
14
12
|
exports.DEFAULT_OPTIONS = {
|
|
15
13
|
limit: 1,
|
|
16
14
|
retries: 1,
|
|
@@ -20,3 +18,8 @@ exports.DEFAULT_OPTIONS = {
|
|
|
20
18
|
auditContext: null,
|
|
21
19
|
enableRabbitTrace: false,
|
|
22
20
|
};
|
|
21
|
+
var ConnectionPurpose;
|
|
22
|
+
(function (ConnectionPurpose) {
|
|
23
|
+
ConnectionPurpose["Consume"] = "consume";
|
|
24
|
+
ConnectionPurpose["Publish"] = "publish";
|
|
25
|
+
})(ConnectionPurpose = exports.ConnectionPurpose || (exports.ConnectionPurpose = {}));
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
2
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
3
|
export interface ExchangesCache {
|
|
4
4
|
[key: string]: any;
|
|
@@ -26,25 +26,25 @@ export interface ConsumeOptions {
|
|
|
26
26
|
useConsumeWithLock?: boolean;
|
|
27
27
|
auditContext?: any;
|
|
28
28
|
enableRabbitTrace?: boolean;
|
|
29
|
-
channelConsumeOptions?: Options.Consume;
|
|
30
29
|
}
|
|
31
30
|
export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>;
|
|
32
31
|
export type newChannelOpts = {
|
|
33
32
|
name?: string;
|
|
34
33
|
onClose?: null | ((args: any | null) => void);
|
|
35
|
-
options?: CreateChannelOpts | undefined;
|
|
36
34
|
};
|
|
37
35
|
export type assertChannelOpts = {
|
|
38
36
|
channelName?: string;
|
|
39
37
|
force?: boolean;
|
|
40
|
-
newChannelOptions?: newChannelOpts;
|
|
41
38
|
};
|
|
42
|
-
export interface PublishOptions {
|
|
43
|
-
newChannelOptions?: newChannelOpts;
|
|
44
|
-
}
|
|
45
39
|
export type AfConsumer = {
|
|
46
40
|
queue: string;
|
|
47
41
|
callback: CallbackFunction;
|
|
48
42
|
options: ConsumeOptions | undefined;
|
|
49
43
|
};
|
|
50
44
|
export declare const CONSUMER_DEFAULT_OPTIONS: Options.Consume;
|
|
45
|
+
export type ConnectionData = {
|
|
46
|
+
connection: AmqpConnectionManager | null;
|
|
47
|
+
creatingConnection: boolean;
|
|
48
|
+
connectionCreatedEventName: string;
|
|
49
|
+
connectionFailedEventName: string;
|
|
50
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autofleet/rabbit",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.26-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"engines": {
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"amqp-connection-manager": "4.1.9",
|
|
23
23
|
"amqplib": "0.10.3",
|
|
24
24
|
"bluebird": "^3.7.2",
|
|
25
|
-
"lodash": "^4.17.21",
|
|
26
25
|
"moment": "^2.29.1",
|
|
27
26
|
"redis": "^3.1.2",
|
|
28
27
|
"redis-lock": "^0.1.4"
|
|
@@ -34,7 +33,6 @@
|
|
|
34
33
|
"@autofleet/logger": "4.0.6",
|
|
35
34
|
"@types/amqplib": "0.8.2",
|
|
36
35
|
"@types/jest": "^29.5.12",
|
|
37
|
-
"@types/lodash": "^4.17.12",
|
|
38
36
|
"@types/node": "^20.14.11",
|
|
39
37
|
"@typescript-eslint/eslint-plugin": "^4.8.1",
|
|
40
38
|
"eslint": "^7.13.0",
|
package/src/index.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { EventEmitter, once } from 'events';
|
|
4
4
|
import { promisify } from 'util';
|
|
5
|
-
import { merge } from 'lodash';
|
|
6
5
|
import moment from 'moment';
|
|
7
6
|
import RedisLock from 'redis-lock';
|
|
8
7
|
import {
|
|
9
|
-
AmqpConnectionManager, ChannelWrapper, connect,
|
|
8
|
+
AmqpConnectionManager, ChannelWrapper, connect, CreateChannelOpts,
|
|
10
9
|
} from 'amqp-connection-manager';
|
|
11
10
|
import {
|
|
12
11
|
ConfirmChannel, ConsumeMessage, Options, Replies,
|
|
@@ -21,8 +20,7 @@ import getRedisInstance, { RedisConfig } from './lib/redis';
|
|
|
21
20
|
import { assertExchangeFanout, rand, wrapSetImmediate } from './lib/utils';
|
|
22
21
|
import {
|
|
23
22
|
AUTOMATION_ID_HEADER,
|
|
24
|
-
|
|
25
|
-
CONNECTION_FAILED_CONST,
|
|
23
|
+
ConnectionPurpose,
|
|
26
24
|
DEFAULT_LOCK_TIMEOUT,
|
|
27
25
|
DEFAULT_OPTIONS,
|
|
28
26
|
RETRY_HEADER,
|
|
@@ -41,16 +39,13 @@ import {
|
|
|
41
39
|
CONSUMER_DEFAULT_OPTIONS,
|
|
42
40
|
QueueSetupPromisesDictionary,
|
|
43
41
|
AssertExchangePromisesDictionary,
|
|
44
|
-
|
|
45
|
-
newChannelOpts,
|
|
46
|
-
PublishOptions,
|
|
42
|
+
ConnectionData,
|
|
47
43
|
} from './lib/types';
|
|
48
44
|
|
|
49
45
|
// const debug = nodeDebug('af-rabbitmq')
|
|
50
46
|
const debug = logger.debug.bind(logger);
|
|
51
47
|
|
|
52
48
|
const PUBLISH_TIMEOUT = 1000 * 10;
|
|
53
|
-
|
|
54
49
|
export interface IAfRabbitMq {
|
|
55
50
|
ack: any;
|
|
56
51
|
nack: any;
|
|
@@ -86,6 +81,19 @@ export interface AfRabbitOptions {
|
|
|
86
81
|
rabbitHost?: string;
|
|
87
82
|
}
|
|
88
83
|
|
|
84
|
+
type newChannelOpts = {
|
|
85
|
+
name?: string;
|
|
86
|
+
onClose?: null | ((args: any | null) => void);
|
|
87
|
+
options?: CreateChannelOpts | undefined;
|
|
88
|
+
connectionPurpose?: ConnectionPurpose,
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
type assertChannelOpts = {
|
|
92
|
+
channelName?: string;
|
|
93
|
+
force?: boolean;
|
|
94
|
+
connectionPurpose?: ConnectionPurpose;
|
|
95
|
+
}
|
|
96
|
+
|
|
89
97
|
type AfConsumer = {
|
|
90
98
|
queue: string;
|
|
91
99
|
callback: CallbackFunction;
|
|
@@ -95,7 +103,7 @@ type AfConsumer = {
|
|
|
95
103
|
const HEARTBEAT = '60';
|
|
96
104
|
|
|
97
105
|
class RabbitMq implements IAfRabbitMq {
|
|
98
|
-
static parseMsg(msg: any)
|
|
106
|
+
static parseMsg(msg: any): any {
|
|
99
107
|
let { content } = msg;
|
|
100
108
|
content = content.toString();
|
|
101
109
|
|
|
@@ -136,18 +144,19 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
136
144
|
|
|
137
145
|
RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
|
|
138
146
|
|
|
139
|
-
|
|
147
|
+
publishChannel: ChannelWrapper | null;
|
|
140
148
|
|
|
141
149
|
publishChannelSetupPromise: Promise<ChannelWrapper> | null;
|
|
142
150
|
|
|
143
|
-
blockReconnect: boolean | null | undefined
|
|
151
|
+
blockReconnect: boolean | null | undefined;
|
|
144
152
|
|
|
145
|
-
|
|
153
|
+
connectionsMap: {
|
|
154
|
+
[ConnectionPurpose.Consume]: ConnectionData;
|
|
155
|
+
[ConnectionPurpose.Publish]: ConnectionData;
|
|
156
|
+
};
|
|
146
157
|
|
|
147
158
|
em: EventEmitter;
|
|
148
159
|
|
|
149
|
-
creatingConnection: boolean;
|
|
150
|
-
|
|
151
160
|
exchanges: ExchangesCache;
|
|
152
161
|
|
|
153
162
|
queues: QueuesCache;
|
|
@@ -169,10 +178,22 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
169
178
|
|
|
170
179
|
constructor(options?: AfRabbitOptions, redisConfig?: RedisConfig) {
|
|
171
180
|
this.em = new EventEmitter();
|
|
172
|
-
this.
|
|
181
|
+
this.publishChannel = null;
|
|
173
182
|
this.publishChannelSetupPromise = null;
|
|
174
|
-
this.
|
|
175
|
-
|
|
183
|
+
this.connectionsMap = {
|
|
184
|
+
[ConnectionPurpose.Consume]: {
|
|
185
|
+
connection: null,
|
|
186
|
+
creatingConnection: false,
|
|
187
|
+
connectionCreatedEventName: 'consumeConnectionCreated',
|
|
188
|
+
connectionFailedEventName: 'consumeConnectionFailed',
|
|
189
|
+
},
|
|
190
|
+
[ConnectionPurpose.Publish]: {
|
|
191
|
+
connection: null,
|
|
192
|
+
creatingConnection: false,
|
|
193
|
+
connectionCreatedEventName: 'publishConnectionCreated',
|
|
194
|
+
connectionFailedEventName: 'publishConnectionFailed',
|
|
195
|
+
},
|
|
196
|
+
};
|
|
176
197
|
this.exchanges = {};
|
|
177
198
|
this.queues = {};
|
|
178
199
|
this.queueSetupPromises = {};
|
|
@@ -209,7 +230,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
209
230
|
return false;
|
|
210
231
|
}
|
|
211
232
|
|
|
212
|
-
public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage)
|
|
233
|
+
public ack = (channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg: ConsumeMessage): Promise<any> => {
|
|
213
234
|
if (msg) {
|
|
214
235
|
debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });
|
|
215
236
|
await channel.ack(msg);
|
|
@@ -235,8 +256,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
235
256
|
userMsg: ConsumeMessageOrNull,
|
|
236
257
|
{
|
|
237
258
|
skipRetry = false,
|
|
238
|
-
}: NackOptions = {
|
|
239
|
-
)
|
|
259
|
+
}: NackOptions = {},
|
|
260
|
+
): Promise<any> => {
|
|
240
261
|
await this.unlockRedisIfNeeded(releaseLock);
|
|
241
262
|
if (channel && msg) {
|
|
242
263
|
if (
|
|
@@ -270,30 +291,36 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
270
291
|
}
|
|
271
292
|
}
|
|
272
293
|
|
|
273
|
-
async getConnection() {
|
|
274
|
-
return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
|
|
294
|
+
async getConnection(connectionPurpose: ConnectionPurpose) {
|
|
295
|
+
return new Promise<AmqpConnectionManager | undefined | null>(async (resolve, reject) => {
|
|
296
|
+
const {
|
|
297
|
+
connection,
|
|
298
|
+
creatingConnection,
|
|
299
|
+
connectionCreatedEventName,
|
|
300
|
+
connectionFailedEventName,
|
|
301
|
+
} = this.connectionsMap[connectionPurpose];
|
|
275
302
|
if (this.blockReconnect) {
|
|
276
303
|
debug('rabbit: block reconnect');
|
|
277
304
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
278
305
|
// @ts-ignore
|
|
279
306
|
return resolve();
|
|
280
307
|
}
|
|
281
|
-
if (
|
|
282
|
-
if (this.options?.disableReconnect ||
|
|
308
|
+
if (connection !== null) {
|
|
309
|
+
if (this.options?.disableReconnect || connection?.isConnected()) {
|
|
283
310
|
debug('rabbit: connection - is connected');
|
|
284
311
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
285
312
|
// @ts-ignore
|
|
286
|
-
return resolve(
|
|
313
|
+
return resolve(connection);
|
|
287
314
|
}
|
|
288
315
|
debug('rabbit: connection - reconnecting');
|
|
289
316
|
}
|
|
290
|
-
if (
|
|
317
|
+
if (creatingConnection) {
|
|
291
318
|
debug('rabbit: creating connection emi');
|
|
292
|
-
this.em.once(
|
|
293
|
-
this.em.once(
|
|
319
|
+
this.em.once(connectionCreatedEventName, resolve);
|
|
320
|
+
this.em.once(connectionFailedEventName, reject);
|
|
294
321
|
return;
|
|
295
322
|
}
|
|
296
|
-
this.creatingConnection = true;
|
|
323
|
+
this.connectionsMap[connectionPurpose].creatingConnection = true;
|
|
297
324
|
let isResolved = false;
|
|
298
325
|
|
|
299
326
|
// It is import to use it as a function and not as a variable
|
|
@@ -310,32 +337,33 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
310
337
|
};
|
|
311
338
|
|
|
312
339
|
const defaultUrls = findServers();
|
|
313
|
-
const
|
|
340
|
+
const newConnection: AmqpConnectionManager = await connect(defaultUrls, {
|
|
314
341
|
findServers,
|
|
315
342
|
});
|
|
316
343
|
|
|
317
|
-
this.connection =
|
|
318
|
-
|
|
344
|
+
this.connectionsMap[connectionPurpose].connection = newConnection;
|
|
345
|
+
logger.info(`rabbit: created new connection ${connectionPurpose}`);
|
|
346
|
+
|
|
347
|
+
newConnection.on('error', (err) => {
|
|
319
348
|
logger.error('rabbit: connection error', { err });
|
|
320
349
|
if (!isResolved) {
|
|
321
350
|
isResolved = true;
|
|
322
351
|
reject(err);
|
|
323
|
-
this.em.emit(
|
|
352
|
+
this.em.emit(connectionFailedEventName, err);
|
|
324
353
|
}
|
|
325
354
|
});
|
|
326
355
|
|
|
327
|
-
|
|
356
|
+
newConnection.on('connectFailed', (err) => {
|
|
328
357
|
this.consumersTags = [];
|
|
329
358
|
logger.error('rabbit: connection connectFailed', { err });
|
|
330
359
|
if (!isResolved) {
|
|
331
360
|
isResolved = true;
|
|
332
361
|
reject(err);
|
|
333
|
-
this.em.emit(
|
|
362
|
+
this.em.emit(connectionFailedEventName, err);
|
|
334
363
|
}
|
|
335
364
|
});
|
|
336
365
|
|
|
337
|
-
|
|
338
|
-
// this.channel = null;
|
|
366
|
+
newConnection.on('disconnect', ({ err }) => {
|
|
339
367
|
this.consumersTags = [];
|
|
340
368
|
debug('rabbit: connection closed');
|
|
341
369
|
if (this.options?.disableReconnect) {
|
|
@@ -345,26 +373,29 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
345
373
|
logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
|
|
346
374
|
}
|
|
347
375
|
});
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
this.creatingConnection = false;
|
|
352
|
-
this.em.emit(CONNECTION_CREATED_CONST, connection);
|
|
376
|
+
newConnection.once('connect', async () => {
|
|
377
|
+
this.connectionsMap[connectionPurpose].creatingConnection = false;
|
|
378
|
+
this.em.emit(connectionCreatedEventName, newConnection);
|
|
353
379
|
isResolved = true;
|
|
354
|
-
resolve(
|
|
380
|
+
resolve(newConnection);
|
|
355
381
|
});
|
|
356
382
|
});
|
|
357
383
|
}
|
|
358
384
|
|
|
359
|
-
async getNewChannel({
|
|
360
|
-
|
|
385
|
+
async getNewChannel({
|
|
386
|
+
name = rand().toString(), onClose = null, options = {}, connectionPurpose = ConnectionPurpose.Consume,
|
|
387
|
+
}: newChannelOpts): Promise<ChannelWrapper> {
|
|
388
|
+
let connection!: AmqpConnectionManager | undefined | null;
|
|
361
389
|
try {
|
|
362
|
-
connection = await this.getConnection();
|
|
390
|
+
connection = await this.getConnection(connectionPurpose);
|
|
363
391
|
} catch (e) {
|
|
364
392
|
logger.error(`rabbit: error on get connection for new channel ${name} `, { e });
|
|
365
393
|
throw e;
|
|
366
394
|
}
|
|
367
|
-
|
|
395
|
+
if (!connection) {
|
|
396
|
+
throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
|
|
397
|
+
}
|
|
398
|
+
const channel = connection.createChannel({ ...options });
|
|
368
399
|
once(channel, 'close').then((args) => {
|
|
369
400
|
logger.error(`rabbit: channel ${name} closed`);
|
|
370
401
|
onClose?.(args);
|
|
@@ -379,19 +410,21 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
379
410
|
}
|
|
380
411
|
}
|
|
381
412
|
|
|
382
|
-
async assertChannel({ force = false,
|
|
413
|
+
async assertChannel({ force = false, connectionPurpose = ConnectionPurpose.Consume }: assertChannelOpts): Promise<ChannelWrapper> {
|
|
414
|
+
debug('rabbit: start assert channel', { connectionPurpose, publishPromise: this.publishChannelSetupPromise, channel: this.publishChannel });
|
|
383
415
|
if (!this.publishChannelSetupPromise) {
|
|
384
416
|
this.publishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
|
|
385
|
-
if (this.
|
|
386
|
-
return resolve(this.
|
|
417
|
+
if (this.publishChannel && !force) {
|
|
418
|
+
return resolve(this.publishChannel);
|
|
387
419
|
}
|
|
388
420
|
|
|
389
421
|
try {
|
|
390
|
-
const channel = await this.getNewChannel({
|
|
422
|
+
const channel = await this.getNewChannel({ connectionPurpose });
|
|
423
|
+
debug('rabbit: new channel got', { connectionPurpose, channel: this.publishChannel });
|
|
391
424
|
channel.on('error', (err) => {
|
|
392
425
|
logger.error('rabbit: channel error', { err });
|
|
393
426
|
});
|
|
394
|
-
this.
|
|
427
|
+
this.publishChannel = channel;
|
|
395
428
|
resolve(channel);
|
|
396
429
|
} catch (e) {
|
|
397
430
|
reject(e);
|
|
@@ -401,9 +434,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
401
434
|
return this.publishChannelSetupPromise;
|
|
402
435
|
}
|
|
403
436
|
|
|
404
|
-
async assertExchange(exchangeName: string) {
|
|
405
|
-
const channel: ChannelWrapper = await this.assertChannel();
|
|
406
|
-
|
|
437
|
+
async assertExchange(exchangeName: string, options: any = { connectionPurpose: ConnectionPurpose.Consume }) {
|
|
438
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: options.connectionPurpose });
|
|
407
439
|
if (this.exchanges[exchangeName]) {
|
|
408
440
|
delete this.assertExchangePromises[exchangeName];
|
|
409
441
|
return this.exchanges[exchangeName];
|
|
@@ -418,32 +450,33 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
418
450
|
return this.exchanges[exchangeName];
|
|
419
451
|
}
|
|
420
452
|
|
|
421
|
-
async getQueueLength(queue: string) {
|
|
453
|
+
async getQueueLength(queue: string, connectionPurpose: ConnectionPurpose = ConnectionPurpose.Consume): Promise<Replies.AssertQueue> {
|
|
422
454
|
RabbitMq.validateName('queue', queue);
|
|
423
|
-
const {
|
|
424
|
-
|
|
455
|
+
const { connection } = this.connectionsMap[connectionPurpose];
|
|
456
|
+
const { publishChannel } = this;
|
|
457
|
+
if (!publishChannel) {
|
|
425
458
|
throw new Error('channel is not defined');
|
|
426
459
|
}
|
|
427
|
-
debug('rabbit: getting queue length', { queue, connected:
|
|
428
|
-
return
|
|
460
|
+
debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
|
|
461
|
+
return publishChannel?.checkQueue(queue);
|
|
429
462
|
}
|
|
430
463
|
|
|
431
|
-
private async deleteQueue(queue: string) {
|
|
464
|
+
private async deleteQueue(queue: string, connectionPurpose: ConnectionPurpose) {
|
|
432
465
|
RabbitMq.validateName('queue', queue);
|
|
433
|
-
const channel: ChannelWrapper = await this.assertChannel();
|
|
466
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose });
|
|
434
467
|
logger.info('rabbit: deleting queue', { queue });
|
|
435
468
|
const deleteQueueRes = await channel.deleteQueue(queue);
|
|
436
469
|
debug('queue deleted', deleteQueueRes);
|
|
437
470
|
return deleteQueueRes;
|
|
438
471
|
}
|
|
439
472
|
|
|
440
|
-
async bindQueue(queue: string, exchange: string) {
|
|
441
|
-
const channel: ChannelWrapper = await this.assertChannel();
|
|
473
|
+
async bindQueue(queue: string, exchange: string, connectionPurpose: ConnectionPurpose) {
|
|
474
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose });
|
|
442
475
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));
|
|
443
476
|
return channel.bindQueue(queue, exchange, '');
|
|
444
477
|
}
|
|
445
478
|
|
|
446
|
-
async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
479
|
+
async setupQueue(queueName: string, connectionPurpose: ConnectionPurpose, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
|
|
447
480
|
let queue: Replies.AssertQueue;
|
|
448
481
|
const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
|
|
449
482
|
const localeOptions = {
|
|
@@ -456,7 +489,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
456
489
|
},
|
|
457
490
|
};
|
|
458
491
|
try {
|
|
459
|
-
const channel: ChannelWrapper = await this.assertChannel();
|
|
492
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose });
|
|
460
493
|
debug('assertQueue->channel.addSetup', { queueName });
|
|
461
494
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
462
495
|
debug('assertQueue->channel.assertQueue', { queueName });
|
|
@@ -465,8 +498,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
465
498
|
logger.error('rabbit: assertQueue error', { queueName, options, error: e });
|
|
466
499
|
if (!this.options?.dontRetryAssert) {
|
|
467
500
|
debug('retrying assertQueue', { queueName });
|
|
468
|
-
const channel = await this.assertChannel({ force: true });
|
|
469
|
-
await this.deleteQueue(queueName);
|
|
501
|
+
const channel = await this.assertChannel({ force: true, connectionPurpose });
|
|
502
|
+
await this.deleteQueue(queueName, connectionPurpose);
|
|
470
503
|
|
|
471
504
|
debug('retrying assertQueue->channel.addSetup', { queueName });
|
|
472
505
|
await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
|
|
@@ -496,7 +529,8 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
496
529
|
return false;
|
|
497
530
|
}
|
|
498
531
|
|
|
499
|
-
async assertQueue(queueName: string, options?: Options.AssertQueue)
|
|
532
|
+
async assertQueue(queueName: string, connectionPurpose: ConnectionPurpose, options?: Options.AssertQueue) {
|
|
533
|
+
debug('rabbit: start assert queue', { connectionPurpose, queueName });
|
|
500
534
|
RabbitMq.validateName('queue', queueName);
|
|
501
535
|
if (this.queues[queueName]) {
|
|
502
536
|
delete this.queueSetupPromises[queueName];
|
|
@@ -507,12 +541,13 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
507
541
|
return this.queueSetupPromises[queueName];
|
|
508
542
|
}
|
|
509
543
|
|
|
510
|
-
this.queueSetupPromises[queueName] = this.setupQueue(queueName, options);
|
|
544
|
+
this.queueSetupPromises[queueName] = this.setupQueue(queueName, connectionPurpose, options);
|
|
545
|
+
debug('rabbit: done assert queue', { connectionPurpose, queueName });
|
|
511
546
|
return this.queueSetupPromises[queueName];
|
|
512
547
|
}
|
|
513
548
|
|
|
514
549
|
private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined) {
|
|
515
|
-
const isConsumerExist
|
|
550
|
+
const isConsumerExist: boolean = this.consumers.some((consumer) => consumer.queue === queue);
|
|
516
551
|
if (!isConsumerExist) {
|
|
517
552
|
logger.info(`rabbit: consumer: ${queue} saved in consumer array`);
|
|
518
553
|
this.consumers.push({
|
|
@@ -561,14 +596,10 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
561
596
|
}
|
|
562
597
|
logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
|
|
563
598
|
}
|
|
564
|
-
const channel = await this.getNewChannel({});
|
|
599
|
+
const channel = await this.getNewChannel({ connectionPurpose: ConnectionPurpose.Consume });
|
|
565
600
|
return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
|
|
566
|
-
const q = await this.assertQueue(queue, optionsWithDefaults);
|
|
601
|
+
const q = await this.assertQueue(queue, ConnectionPurpose.Consume, optionsWithDefaults);
|
|
567
602
|
await confirmChannel.prefetch(limit, false);
|
|
568
|
-
const channelConsumerOptions = optionsWithDefaults.channelConsumeOptions
|
|
569
|
-
? merge(CONSUMER_DEFAULT_OPTIONS, optionsWithDefaults.channelConsumeOptions)
|
|
570
|
-
: CONSUMER_DEFAULT_OPTIONS;
|
|
571
|
-
|
|
572
603
|
const { consumerTag } = await confirmChannel.consume(
|
|
573
604
|
queue,
|
|
574
605
|
async (msg: ConsumeMessageOrNull) => {
|
|
@@ -644,8 +675,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
644
675
|
} catch (e) {
|
|
645
676
|
await localNack(msg);
|
|
646
677
|
}
|
|
647
|
-
},
|
|
648
|
-
channelConsumerOptions,
|
|
678
|
+
}, CONSUMER_DEFAULT_OPTIONS,
|
|
649
679
|
);
|
|
650
680
|
if (!consumerTag) {
|
|
651
681
|
logger.error(`rabbit: failed to consume from queue ${queue}`);
|
|
@@ -656,19 +686,19 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
656
686
|
});
|
|
657
687
|
}
|
|
658
688
|
|
|
659
|
-
async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions)
|
|
689
|
+
async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
|
|
660
690
|
const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };
|
|
661
691
|
RabbitMq.validateName('exchange', exchange);
|
|
662
692
|
RabbitMq.validateName('queue', queue);
|
|
663
693
|
const { limit, deadMessageTtl } = optionsWithDefaults;
|
|
664
694
|
await this.saveConsumer(queue, callback, options);
|
|
665
|
-
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume-exchange
|
|
695
|
+
const channel: ChannelWrapper = await this.getNewChannel({ name: `consume - exchange - ${exchange} -queue - ${queue}` });
|
|
666
696
|
|
|
667
697
|
return channel.addSetup(async (c: ConfirmChannel) => {
|
|
668
698
|
const assertExchange = await assertExchangeFanout(c, exchange);
|
|
669
699
|
await c.assertQueue(queue);
|
|
670
700
|
this.exchanges[exchange] = assertExchange;
|
|
671
|
-
await c.prefetch(limit,
|
|
701
|
+
await c.prefetch(limit, true);
|
|
672
702
|
return Promise.all([
|
|
673
703
|
c.bindQueue(queue, exchange, ''),
|
|
674
704
|
this.consume(
|
|
@@ -680,11 +710,12 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
680
710
|
});
|
|
681
711
|
}
|
|
682
712
|
|
|
683
|
-
async publish(exchange: string, content: any, customHeaders?: any
|
|
713
|
+
async publish(exchange: string, content: any, customHeaders?: any): Promise<boolean> {
|
|
714
|
+
debug('rabbit: start publish msg');
|
|
684
715
|
return wrapSetImmediate(async () => {
|
|
685
716
|
RabbitMq.validateName('exchange', exchange);
|
|
686
|
-
const channel: ChannelWrapper = await this.assertChannel({
|
|
687
|
-
await this.assertExchange(exchange);
|
|
717
|
+
const channel: ChannelWrapper = await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
|
|
718
|
+
await this.assertExchange(exchange, { connectionPurpose: ConnectionPurpose.Publish });
|
|
688
719
|
await channel.publish(exchange, '',
|
|
689
720
|
Buffer.from(JSON.stringify(content)),
|
|
690
721
|
RabbitMq.getPublishOptions(customHeaders));
|
|
@@ -698,7 +729,7 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
698
729
|
customHeaders?: any,
|
|
699
730
|
): Promise<boolean | undefined> {
|
|
700
731
|
try {
|
|
701
|
-
await this.assertChannel({
|
|
732
|
+
await this.assertChannel({ connectionPurpose: ConnectionPurpose.Publish });
|
|
702
733
|
} catch (e) {
|
|
703
734
|
logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
|
|
704
735
|
throw e;
|
|
@@ -706,47 +737,55 @@ class RabbitMq implements IAfRabbitMq {
|
|
|
706
737
|
|
|
707
738
|
try {
|
|
708
739
|
RabbitMq.validateName('queue', queue);
|
|
709
|
-
await this.assertQueue(queue, options);
|
|
740
|
+
await this.assertQueue(queue, ConnectionPurpose.Publish, options);
|
|
710
741
|
} catch (e) {
|
|
711
742
|
logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
|
|
712
743
|
throw e;
|
|
713
744
|
}
|
|
714
745
|
|
|
715
746
|
try {
|
|
716
|
-
const res = await this.
|
|
747
|
+
const res = await this.publishChannel?.sendToQueue(queue,
|
|
717
748
|
Buffer.from(JSON.stringify(content)),
|
|
718
749
|
RabbitMq.getPublishOptions(customHeaders));
|
|
719
750
|
debug(`rabbit: sending to queue ${queue}`, { res });
|
|
720
751
|
return res;
|
|
721
752
|
} catch (e) {
|
|
722
|
-
|
|
723
|
-
logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
|
|
753
|
+
logger.error(`rabbit sendToQueue: failed to send to queue ${queue}`, { e });
|
|
724
754
|
throw e;
|
|
725
755
|
}
|
|
726
756
|
}
|
|
727
757
|
|
|
728
|
-
async isConnected()
|
|
729
|
-
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
758
|
+
async isConnected(): Promise<boolean> {
|
|
759
|
+
debug('rabbit: start is connected');
|
|
760
|
+
const isEachConnectionConnected = await Promise.all(
|
|
761
|
+
Object.entries(this.connectionsMap).map(async ([connectionPurpose, connectionData]) => {
|
|
762
|
+
const { connection } = connectionData;
|
|
763
|
+
debug('rabbit: is connected inside map', { connection, connectionPurpose });
|
|
764
|
+
const isConnected = connection?.isConnected();
|
|
765
|
+
if (!isConnected) {
|
|
766
|
+
logger.error('rabbit: isConnected - false', { connectionPurpose });
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
if (connectionPurpose === ConnectionPurpose.Publish) {
|
|
770
|
+
const channel: any = await this.assertChannel({ connectionPurpose: connectionPurpose as ConnectionPurpose });
|
|
771
|
+
try {
|
|
772
|
+
await Promise.all([
|
|
773
|
+
channel.waitForConnect(),
|
|
774
|
+
...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
|
|
775
|
+
]);
|
|
776
|
+
} catch (e) {
|
|
777
|
+
logger.error('rabbit: isConnected - false');
|
|
778
|
+
return false;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
logger.info('rabbit: isConnected - true');
|
|
782
|
+
return true;
|
|
783
|
+
}),
|
|
784
|
+
);
|
|
785
|
+
return isEachConnectionConnected.every((isConnected) => isConnected === true);
|
|
747
786
|
}
|
|
748
787
|
|
|
749
|
-
async gracefulShutdown(signal: string)
|
|
788
|
+
async gracefulShutdown(signal: string): Promise<void> {
|
|
750
789
|
const tagsNumber = this.consumersTags.length;
|
|
751
790
|
logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);
|
|
752
791
|
const cancelTagPromises = this.consumersTags.map(([channel, tag]) => channel.cancel(tag));
|
package/src/lib/consts.ts
CHANGED
|
@@ -6,8 +6,6 @@ export const USER_TRACING_HEADER = 'x-af-user-id';
|
|
|
6
6
|
export const AUTOMATION_ID_HEADER = 'x-af-automation-id';
|
|
7
7
|
export const USER_OBJECT = 'userObject';
|
|
8
8
|
export const DEFAULT_USE_CONSUME_WITH_LOCK = false;
|
|
9
|
-
export const CONNECTION_CREATED_CONST = 'connectionCreated';
|
|
10
|
-
export const CONNECTION_FAILED_CONST = 'connectionFailed';
|
|
11
9
|
export const DEFAULT_OPTIONS = {
|
|
12
10
|
limit: 1,
|
|
13
11
|
retries: 1,
|
|
@@ -17,3 +15,8 @@ export const DEFAULT_OPTIONS = {
|
|
|
17
15
|
auditContext: null,
|
|
18
16
|
enableRabbitTrace: false,
|
|
19
17
|
};
|
|
18
|
+
|
|
19
|
+
export enum ConnectionPurpose {
|
|
20
|
+
Consume = 'consume',
|
|
21
|
+
Publish = 'publish',
|
|
22
|
+
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AmqpConnectionManager } from 'amqp-connection-manager';
|
|
2
2
|
import { ConsumeMessage, Options, Replies } from 'amqplib';
|
|
3
3
|
|
|
4
4
|
export interface ExchangesCache {
|
|
@@ -32,7 +32,6 @@ export interface ConsumeOptions {
|
|
|
32
32
|
useConsumeWithLock?: boolean;
|
|
33
33
|
auditContext?: any;
|
|
34
34
|
enableRabbitTrace?: boolean;
|
|
35
|
-
channelConsumeOptions?: Options.Consume;
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Promise<any>
|
|
@@ -40,18 +39,11 @@ export type CallbackFunction = (msg: ConsumeMessage, ack: any, nack: any) => Pro
|
|
|
40
39
|
export type newChannelOpts = {
|
|
41
40
|
name?: string;
|
|
42
41
|
onClose?: null | ((args: any | null) => void);
|
|
43
|
-
options?: CreateChannelOpts | undefined;
|
|
44
42
|
};
|
|
45
43
|
export type assertChannelOpts = {
|
|
46
44
|
channelName?: string;
|
|
47
45
|
force?: boolean;
|
|
48
|
-
newChannelOptions?: newChannelOpts;
|
|
49
46
|
}
|
|
50
|
-
|
|
51
|
-
export interface PublishOptions {
|
|
52
|
-
newChannelOptions?: newChannelOpts;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
47
|
export type AfConsumer = {
|
|
56
48
|
queue: string;
|
|
57
49
|
callback: CallbackFunction;
|
|
@@ -68,3 +60,10 @@ export const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {
|
|
|
68
60
|
[HA_PROMOTE_ON_SHUTDOWN]: 'always',
|
|
69
61
|
},
|
|
70
62
|
};
|
|
63
|
+
|
|
64
|
+
export type ConnectionData = {
|
|
65
|
+
connection: AmqpConnectionManager | null;
|
|
66
|
+
creatingConnection: boolean;
|
|
67
|
+
connectionCreatedEventName: string;
|
|
68
|
+
connectionFailedEventName: string;
|
|
69
|
+
};
|