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