@autofleet/rabbit 3.2.2-2.beta-0 → 3.2.2

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.js CHANGED
@@ -10,7 +10,6 @@ const moment_1 = __importDefault(require("moment"));
10
10
  const redis_lock_1 = __importDefault(require("redis-lock"));
11
11
  const amqp_connection_manager_1 = require("amqp-connection-manager");
12
12
  const zehut_1 = require("@autofleet/zehut");
13
- const node_crypto_1 = require("node:crypto");
14
13
  const logger_1 = __importDefault(require("./logger"));
15
14
  const rabbitError_1 = __importDefault(require("./lib/rabbitError"));
16
15
  const redis_1 = __importDefault(require("./lib/redis"));
@@ -18,43 +17,10 @@ const utils_1 = require("./lib/utils");
18
17
  const consts_1 = require("./lib/consts");
19
18
  const types_1 = require("./lib/types");
20
19
  // const debug = nodeDebug('af-rabbitmq')
21
- const debug = logger_1.default.debug.bind(logger_1.default);
20
+ const debug = logger_1.default.info;
22
21
  const PUBLISH_TIMEOUT = 1000 * 10;
23
22
  const HEARTBEAT = '60';
24
23
  class RabbitMq {
25
- static parseMsg(msg) {
26
- let { content } = msg;
27
- content = content.toString();
28
- try {
29
- content = JSON.parse(content);
30
- }
31
- catch (e) { }
32
- return {
33
- ...msg,
34
- content,
35
- };
36
- }
37
- static validateName(type, name) {
38
- if (!name || name === '') {
39
- throw new rabbitError_1.default(`error while using ${type} with no name`);
40
- }
41
- }
42
- static getPublishOptions(customHeaders = {}) {
43
- const trace = (0, zehut_1.getCurrentPayload)();
44
- const user = trace?.context?.get(consts_1.USER_OBJECT);
45
- const traceId = trace?.context?.get(consts_1.TRACING_HEADER);
46
- const outbreakTrace = zehut_1.outbreak.getCurrentContext();
47
- return {
48
- timestamp: (0, moment_1.default)().unix(),
49
- timeout: PUBLISH_TIMEOUT,
50
- headers: {
51
- creationTimestamp: (0, moment_1.default)().valueOf(),
52
- ...customHeaders,
53
- [consts_1.USER_TRACING_HEADER]: user?.id,
54
- [consts_1.TRACING_HEADER]: traceId || outbreakTrace?.context?.get(consts_1.TRACING_HEADER),
55
- },
56
- };
57
- }
58
24
  constructor(options, redisConfig) {
59
25
  this.DISCONNECT_MSG = 'rabbit: connection disconnect';
60
26
  this.RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';
@@ -73,7 +39,6 @@ class RabbitMq {
73
39
  };
74
40
  this.ack = (channel, msg, shouldUpdateRedisTimestamp = false, releaseLock = null) => async (userMsg) => {
75
41
  if (msg) {
76
- debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });
77
42
  await channel.ack(msg);
78
43
  const { properties: { headers } } = msg;
79
44
  const timestamp = headers?.creationTimestamp;
@@ -106,30 +71,25 @@ class RabbitMq {
106
71
  : 1,
107
72
  });
108
73
  }
109
- debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });
110
74
  await channel.ack(msg);
111
75
  }
112
76
  else {
113
77
  logger_1.default.error('no channel or msg', {
78
+ channel: channel ? channel.name : '',
114
79
  msg,
115
80
  });
116
81
  }
117
82
  };
118
83
  this.em = new events_1.EventEmitter();
119
84
  this.channel = null;
120
- this.publishChannelSetupPromise = null;
121
- this.connectionsMap = {
122
- [types_1.ConnectionPurpose.Consume]: { connection: null, creatingConnection: false },
123
- [types_1.ConnectionPurpose.Publish]: { connection: null, creatingConnection: false },
124
- };
85
+ this.connection = null;
86
+ this.creatingConnection = false;
125
87
  this.exchanges = {};
126
88
  this.queues = {};
127
- this.queueSetupPromises = {};
128
- this.consumers = [];
129
89
  this.options = options;
130
- this.redisClient = redisConfig && (0, redis_1.default)(redisConfig);
90
+ this.redisClient = redisConfig && redis_1.default(redisConfig);
131
91
  if (this.redisClient) {
132
- this.redisLock = (0, util_1.promisify)((0, redis_lock_1.default)(this.redisClient));
92
+ this.redisLock = util_1.promisify(redis_lock_1.default(this.redisClient));
133
93
  }
134
94
  this.consumersTags = [];
135
95
  logger_1.default.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);
@@ -142,35 +102,64 @@ class RabbitMq {
142
102
  });
143
103
  }
144
104
  }
145
- async getConnection(connectionPurpose) {
105
+ static parseMsg(msg) {
106
+ let { content } = msg;
107
+ content = content.toString();
108
+ try {
109
+ content = JSON.parse(content);
110
+ }
111
+ catch (e) { }
112
+ return {
113
+ ...msg,
114
+ content,
115
+ };
116
+ }
117
+ static validateName(type, name) {
118
+ if (!name || name === '') {
119
+ throw new rabbitError_1.default(`error while using ${type} with no name`);
120
+ }
121
+ }
122
+ static getPublishOptions(customHeaders = {}) {
123
+ const trace = zehut_1.getCurrentPayload();
124
+ const user = trace?.context?.get(consts_1.USER_OBJECT);
125
+ const traceId = trace?.context?.get(consts_1.TRACING_HEADER);
126
+ const outbreakTrace = zehut_1.outbreak.getCurrentContext();
127
+ return {
128
+ timestamp: moment_1.default().unix(),
129
+ timeout: PUBLISH_TIMEOUT,
130
+ headers: {
131
+ creationTimestamp: moment_1.default().valueOf(),
132
+ ...customHeaders,
133
+ [consts_1.USER_TRACING_HEADER]: user?.id,
134
+ [consts_1.TRACING_HEADER]: traceId || outbreakTrace?.context?.get(consts_1.TRACING_HEADER),
135
+ },
136
+ };
137
+ }
138
+ async getConnection() {
146
139
  return new Promise(async (resolve, reject) => {
147
- let { connection, creatingConnection } = this.connectionsMap[connectionPurpose];
148
140
  if (this.blockReconnect) {
149
141
  debug('rabbit: block reconnect');
150
142
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
151
143
  // @ts-ignore
152
144
  return resolve();
153
145
  }
154
- if (connection !== null) {
155
- if (this.options?.disableReconnect || connection?.isConnected()) {
146
+ if (this.connection !== null) {
147
+ if (this.options?.disableReconnect || this.connection?.isConnected()) {
156
148
  debug('rabbit: connection - is connected');
157
149
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
158
150
  // @ts-ignore
159
- return resolve(connection);
151
+ return resolve(this.connection);
160
152
  }
161
153
  debug('rabbit: connection - reconnecting');
162
154
  }
163
- if (creatingConnection) {
155
+ if (this.creatingConnection) {
164
156
  debug('rabbit: creating connection emi');
165
157
  this.em.once(consts_1.CONNECTION_CREATED_CONST, resolve);
166
158
  this.em.once(consts_1.CONNECTION_FAILED_CONST, reject);
167
159
  return;
168
160
  }
169
- this.connectionsMap[connectionPurpose].creatingConnection = true;
161
+ this.creatingConnection = true;
170
162
  let isResolved = false;
171
- // It is import to use it as a function and not as a variable
172
- // because of k8s changes the env variables
173
- // and we want to use the new values
174
163
  const findServers = () => {
175
164
  const userName = process.env.RABBITMQ_USERNAME || 'guest';
176
165
  const password = process.env.RABBITMQ_PASSWORD || 'guest';
@@ -179,15 +168,11 @@ class RabbitMq {
179
168
  return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];
180
169
  };
181
170
  const defaultUrls = findServers();
182
- const newConnection = await (0, amqp_connection_manager_1.connect)(defaultUrls, {
171
+ const connection = await amqp_connection_manager_1.connect(defaultUrls, {
183
172
  findServers,
184
173
  });
185
- if (!newConnection) {
186
- logger_1.default.error('rabbit: couldnt create a connection');
187
- return resolve(connection);
188
- }
189
- this.connectionsMap[connectionPurpose].connection = newConnection;
190
- newConnection.on('error', (err) => {
174
+ this.connection = connection;
175
+ this.connection.on('error', (err) => {
191
176
  logger_1.default.error('rabbit: connection error', { err });
192
177
  if (!isResolved) {
193
178
  isResolved = true;
@@ -195,8 +180,7 @@ class RabbitMq {
195
180
  this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
196
181
  }
197
182
  });
198
- newConnection.on('connectFailed', (err) => {
199
- this.consumersTags = [];
183
+ this.connection.on('connectFailed', (err) => {
200
184
  logger_1.default.error('rabbit: connection connectFailed', { err });
201
185
  if (!isResolved) {
202
186
  isResolved = true;
@@ -204,9 +188,10 @@ class RabbitMq {
204
188
  this.em.emit(consts_1.CONNECTION_FAILED_CONST, err);
205
189
  }
206
190
  });
207
- newConnection.on('disconnect', ({ err }) => {
208
- this.consumersTags = [];
191
+ this.connection.on('disconnect', ({ err }) => {
209
192
  debug('rabbit: connection closed');
193
+ this.exchanges = {};
194
+ this.queues = {};
210
195
  if (this.options?.disableReconnect) {
211
196
  logger_1.default.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);
212
197
  this.blockReconnect = true;
@@ -215,99 +200,95 @@ class RabbitMq {
215
200
  logger_1.default.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);
216
201
  }
217
202
  });
218
- newConnection.once('connect', async () => {
203
+ this.connection.once('connect', async () => {
219
204
  debug('rabbit: connection established');
220
- this.connectionsMap[connectionPurpose].creatingConnection = false;
221
- this.em.emit(consts_1.CONNECTION_CREATED_CONST, newConnection);
205
+ await this.loadConsumers();
206
+ this.creatingConnection = false;
207
+ this.em.emit(consts_1.CONNECTION_CREATED_CONST, connection);
222
208
  isResolved = true;
223
- resolve(newConnection);
209
+ resolve(connection);
224
210
  });
225
211
  });
226
212
  }
227
- async getNewChannel({ name = (0, utils_1.rand)().toString(), onClose = null, options = {}, connectionPurpose = types_1.ConnectionPurpose.Consume, }) {
228
- let connection;
229
- try {
230
- connection = await this.getConnection(connectionPurpose);
231
- }
232
- catch (e) {
233
- logger_1.default.error(`rabbit: error on get connection for new channel ${name} `, { e });
234
- throw e;
235
- }
236
- if (!connection) {
237
- throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
238
- }
239
- const channel = connection.createChannel({ ...options });
240
- (0, events_1.once)(channel, 'close').then((args) => {
241
- logger_1.default.error(`rabbit: channel ${name} closed`);
242
- onClose?.(args);
243
- });
244
- try {
245
- await (0, events_1.once)(channel, 'connect');
246
- debug(`rabbit: channel ${name} CONNECTED`);
247
- return channel;
248
- }
249
- catch (err) {
250
- logger_1.default.error(`rabbit: channel error ${name} error`, { err });
251
- throw err;
252
- }
253
- }
254
- async assertChannel({ force = false, connectionPurpose = types_1.ConnectionPurpose.Consume }) {
255
- if (!this.publishChannelSetupPromise) {
256
- this.publishChannelSetupPromise = new Promise(async (resolve, reject) => {
257
- if (this.channel && !force) {
258
- return resolve(this.channel);
259
- }
260
- try {
261
- const channel = await this.getNewChannel({ connectionPurpose });
262
- channel.on('error', (err) => {
263
- logger_1.default.error('rabbit: channel error', { err });
264
- });
265
- this.channel = channel;
266
- resolve(channel);
213
+ async getNewChannel({ name = utils_1.rand().toString(), onClose = null } = {}) {
214
+ return new Promise(async (resolve, reject) => {
215
+ const connection = await this.getConnection();
216
+ const channel = connection.createChannel({});
217
+ let isResolved = false;
218
+ channel.on('error', (err) => {
219
+ logger_1.default.error(`rabbit: channel ${name} error`, { err });
220
+ if (!isResolved) {
221
+ isResolved = true;
222
+ reject(err);
267
223
  }
268
- catch (e) {
269
- reject(e);
224
+ });
225
+ channel.on('close', (...args) => {
226
+ logger_1.default.error(`rabbit: channel ${name} closed`, { args });
227
+ if (onClose) {
228
+ onClose(args);
270
229
  }
271
230
  });
272
- }
273
- return this.publishChannelSetupPromise;
231
+ channel.once('connect', () => {
232
+ debug(`rabbit: channel ${name} CONNECTED`);
233
+ isResolved = true;
234
+ resolve(channel);
235
+ });
236
+ });
237
+ }
238
+ async assertChannel({ force = false } = {}) {
239
+ return new Promise(async (resolve, reject) => {
240
+ if (this.channel && !force) {
241
+ return resolve(this.channel);
242
+ }
243
+ try {
244
+ const channel = await this.getNewChannel({});
245
+ channel.on('error', (err) => {
246
+ logger_1.default.error('rabbit: channel error', { err });
247
+ });
248
+ this.channel = channel;
249
+ resolve(channel);
250
+ }
251
+ catch (e) {
252
+ reject(e);
253
+ }
254
+ });
274
255
  }
275
256
  async assertExchange(exchangeName, options) {
276
- const channel = await this.assertChannel({ connectionPurpose: options.connectionPurpose });
257
+ const channel = await this.assertChannel();
277
258
  if (this.exchanges[exchangeName]) {
278
259
  return this.exchanges[exchangeName];
279
260
  }
280
- const exchange = await (0, utils_1.assertExchangeFanout)(channel, exchangeName);
261
+ const exchange = await utils_1.assertExchangeFanout(channel, exchangeName);
281
262
  this.exchanges[exchangeName] = exchange;
282
263
  return exchange;
283
264
  }
284
- async getQueueLength(queue, connectionPurpose = types_1.ConnectionPurpose.Consume) {
265
+ async getQueueLength(queue) {
285
266
  RabbitMq.validateName('queue', queue);
286
- let { connection } = this.connectionsMap[connectionPurpose];
287
- const { channel } = this;
288
- if (!channel) {
289
- throw new Error('channel is not defined');
290
- }
291
- debug('rabbit: getting queue length', { queue, connected: connection?.isConnected() });
292
- return channel?.checkQueue(queue);
267
+ const channel = await this.assertChannel();
268
+ debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
269
+ return channel.checkQueue(queue);
293
270
  }
294
- async deleteQueue(queue, connectionPurpose) {
271
+ async deleteQueue(queue) {
295
272
  RabbitMq.validateName('queue', queue);
296
- const channel = await this.assertChannel({ connectionPurpose });
273
+ const channel = await this.assertChannel();
297
274
  logger_1.default.info('rabbit: deleting queue', { queue });
298
275
  const deleteQueueRes = await channel.deleteQueue(queue);
299
276
  debug('queue deleted', deleteQueueRes);
300
277
  return deleteQueueRes;
301
278
  }
302
- async bindQueue(queue, exchange, connectionPurpose) {
303
- const channel = await this.assertChannel({ connectionPurpose });
279
+ async bindQueue(queue, exchange) {
280
+ const channel = await this.assertChannel();
304
281
  await channel.addSetup((setupChannel) => setupChannel.bindQueue(queue, exchange, ''));
305
282
  return channel.bindQueue(queue, exchange, '');
306
283
  }
307
- async setupQueue(queueName, connectionPurpose, options) {
308
- let queue;
284
+ async assertQueue(queueName, options) {
285
+ let queue = null;
286
+ RabbitMq.validateName('queue', queueName);
287
+ if (this.queues[queueName]) {
288
+ return this.queues[queueName];
289
+ }
309
290
  try {
310
- const channel = await this.assertChannel({ connectionPurpose });
291
+ const channel = await this.assertChannel();
311
292
  debug('assertQueue->channel.addSetup', { queueName });
312
293
  await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
313
294
  debug('assertQueue->channel.assertQueue', { queueName });
@@ -317,11 +298,11 @@ class RabbitMq {
317
298
  logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
318
299
  if (!this.options?.dontRetryAssert) {
319
300
  debug('retrying assertQueue', { queueName });
320
- const channel = await this.assertChannel({ force: true, connectionPurpose });
321
- await this.deleteQueue(queueName, connectionPurpose);
322
- debug('retrying assertQueue->channel.addSetup', { queueName });
301
+ const channel = await this.assertChannel({ force: true });
302
+ await this.deleteQueue(queueName);
303
+ debug('1assertQueue->channel.addSetup', { queueName });
323
304
  await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
324
- debug('retrying assertQueue->channel.assertQueue', { queueName });
305
+ debug('1assertQueue->channel.assertQueue', { queueName });
325
306
  queue = await channel.assertQueue(queueName, options);
326
307
  }
327
308
  else {
@@ -331,31 +312,25 @@ class RabbitMq {
331
312
  this.queues[queueName] = queueName;
332
313
  return queue;
333
314
  }
334
- async assertQueue(queueName, connectionPurpose, options) {
335
- RabbitMq.validateName('queue', queueName);
336
- if (this.queues[queueName]) {
337
- delete this.queueSetupPromises[queueName];
338
- return this.queues[queueName];
339
- }
340
- if (this.queueSetupPromises[queueName]) {
341
- return this.queueSetupPromises[queueName];
342
- }
343
- this.queueSetupPromises[queueName] = this.setupQueue(queueName, connectionPurpose, options);
344
- return this.queueSetupPromises[queueName];
345
- }
346
315
  saveConsumer(queue, callback, options) {
347
- const isConsumerExist = this.consumers.some((consumer) => consumer.queue === queue);
348
- if (!isConsumerExist) {
349
- logger_1.default.info(`rabbit: consumer: ${queue} saved in consumer array`);
350
- this.consumers.push({
351
- queue,
352
- callback,
353
- options,
354
- });
316
+ this.consumers.push({
317
+ queue,
318
+ callback,
319
+ options,
320
+ });
321
+ }
322
+ async loadConsumers() {
323
+ debug('rabbit: loading consumers', { consumers: this.consumers.length });
324
+ if (this.consumers.length > 0) {
325
+ await Promise.all(this.consumers.map((consumer) => this
326
+ .consumeFromRabbit(consumer.queue, consumer.callback, consumer.options)));
355
327
  }
356
328
  }
357
329
  async consume(queue, callback, options) {
358
- await this.consumeFromRabbit(queue, callback, options);
330
+ if (this.connection && !this.creatingConnection) {
331
+ this.consumeFromRabbit(queue, callback, options);
332
+ }
333
+ return this.saveConsumer(queue, callback, options);
359
334
  }
360
335
  async lockRedisIfNeeded(msg, options) {
361
336
  const { properties: { headers } } = msg;
@@ -374,8 +349,6 @@ class RabbitMq {
374
349
  async consumeFromRabbit(queue, callback, options) {
375
350
  const optionsWithDefaults = { ...consts_1.DEFAULT_OPTIONS, ...options };
376
351
  RabbitMq.validateName('queue', queue);
377
- this.saveConsumer(queue, callback, options);
378
- const uniqueId = (0, node_crypto_1.randomUUID)();
379
352
  const { limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace, } = optionsWithDefaults;
380
353
  if (useConsumeWithLock) {
381
354
  if (!this.redisLock) {
@@ -383,11 +356,11 @@ class RabbitMq {
383
356
  }
384
357
  logger_1.default.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);
385
358
  }
386
- const channel = await this.getNewChannel({ connectionPurpose: types_1.ConnectionPurpose.Consume });
387
- return channel.addSetup(async (confirmChannel) => {
388
- await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
389
- await confirmChannel.prefetch(limit, true);
390
- const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
359
+ const channel = await this.getNewChannel({ name: `consume-queue-${queue}` });
360
+ return channel.addSetup(async (c) => {
361
+ await c.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
362
+ await c.prefetch(limit, true);
363
+ const { consumerTag } = await c.consume(queue, async (msg) => {
391
364
  if (!msg) {
392
365
  return null;
393
366
  }
@@ -395,7 +368,7 @@ class RabbitMq {
395
368
  const userId = msg.properties.headers[consts_1.USER_TRACING_HEADER];
396
369
  const parsedMessage = RabbitMq.parseMsg(msg);
397
370
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
398
- const trace = (0, zehut_1.newTrace)(zehut_1.traceTypes.RABBIT);
371
+ const trace = zehut_1.newTrace(zehut_1.traceTypes.RABBIT);
399
372
  // setting also outbreak trace as part of legacy code
400
373
  const outbreakTrace = zehut_1.outbreak.newTrace(zehut_1.traceTypes.RABBIT);
401
374
  // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission
@@ -403,13 +376,13 @@ class RabbitMq {
403
376
  if (userId && enableRabbitTrace) {
404
377
  try {
405
378
  await Promise.all([
406
- (0, zehut_1.createOrSetRabbitTrace)(trace, userId),
407
- (0, zehut_1.createOrSetRabbitTrace)(outbreakTrace, userId),
379
+ zehut_1.createOrSetRabbitTrace(trace, userId),
380
+ zehut_1.createOrSetRabbitTrace(outbreakTrace, userId),
408
381
  ]);
409
382
  }
410
383
  catch (e) {
411
384
  logger_1.default.error('rabbit: failed to setRabbitTrace', { userId, e });
412
- return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
385
+ await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
413
386
  }
414
387
  }
415
388
  if (traceId) {
@@ -422,30 +395,13 @@ class RabbitMq {
422
395
  const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);
423
396
  if (!shouldConsume) {
424
397
  await this.unlockRedisIfNeeded(releaseLock);
425
- return this.ack(confirmChannel, msg)(msg);
398
+ return this.ack(channel, msg)(msg);
426
399
  }
427
- let messageAcked = false;
428
- // setting the localAck function to be used in the callback
429
- const localAck = async () => {
430
- if (messageAcked) {
431
- return;
432
- }
433
- messageAcked = true;
434
- return this.ack(confirmChannel, msg, true, releaseLock)(msg);
435
- };
436
- const localNack = async (_, nackOptions = {}) => {
437
- if (messageAcked) {
438
- return;
439
- }
440
- debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });
441
- messageAcked = true;
442
- return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);
443
- };
444
400
  try {
445
- await callback(parsedMessage, localAck, localNack);
401
+ await callback(parsedMessage, this.ack(channel, msg, true, releaseLock), this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock));
446
402
  }
447
403
  catch (e) {
448
- await localNack(msg);
404
+ await this.nack(channel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);
449
405
  }
450
406
  }, types_1.CONSUMER_DEFAULT_OPTIONS);
451
407
  if (!consumerTag) {
@@ -453,7 +409,7 @@ class RabbitMq {
453
409
  }
454
410
  else {
455
411
  logger_1.default.info(`rabbit: adding tag ${consumerTag} to the array.`);
456
- this.consumersTags.push([confirmChannel, consumerTag]);
412
+ this.consumersTags.push([c, consumerTag]);
457
413
  }
458
414
  });
459
415
  }
@@ -462,10 +418,9 @@ class RabbitMq {
462
418
  RabbitMq.validateName('exchange', exchange);
463
419
  RabbitMq.validateName('queue', queue);
464
420
  const { limit, deadMessageTtl } = optionsWithDefaults;
465
- await this.saveConsumer(queue, callback, options);
466
- const channel = await this.getNewChannel({ name: `consume - exchange - ${exchange} -queue - ${queue}`, connectionPurpose: types_1.ConnectionPurpose.Consume });
421
+ const channel = await this.getNewChannel({ name: `consume-exchange-${exchange}-queue-${queue}` });
467
422
  return channel.addSetup(async (c) => {
468
- const assertExchange = await (0, utils_1.assertExchangeFanout)(c, exchange);
423
+ const assertExchange = await utils_1.assertExchangeFanout(c, exchange);
469
424
  await c.assertQueue(queue);
470
425
  this.exchanges[exchange] = assertExchange;
471
426
  await c.prefetch(limit, true);
@@ -476,64 +431,36 @@ class RabbitMq {
476
431
  });
477
432
  }
478
433
  async publish(exchange, content, customHeaders) {
479
- return (0, utils_1.wrapSetImmediate)(async () => {
434
+ return utils_1.wrapSetImmediate(async () => {
480
435
  RabbitMq.validateName('exchange', exchange);
481
- const channel = await this.assertChannel({ connectionPurpose: types_1.ConnectionPurpose.Publish });
482
- await this.assertExchange(exchange, { connectionPurpose: types_1.ConnectionPurpose.Publish });
436
+ const channel = await this.assertChannel();
437
+ await this.assertExchange(exchange);
483
438
  await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
484
439
  });
485
440
  }
486
- async sendToQueue(queue, content, options, customHeaders) {
487
- try {
488
- await this.assertChannel({ connectionPurpose: types_1.ConnectionPurpose.Publish });
489
- }
490
- catch (e) {
491
- logger_1.default.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });
492
- throw e;
493
- }
494
- try {
495
- RabbitMq.validateName('queue', queue);
496
- await this.assertQueue(queue, types_1.ConnectionPurpose.Publish, options);
497
- }
498
- catch (e) {
499
- logger_1.default.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });
500
- throw e;
501
- }
502
- try {
503
- const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
504
- debug(`rabbit: sending to queue ${queue}`, { res });
505
- return res;
506
- }
507
- catch (e) {
508
- const isConnected = await this.isConnected(types_1.ConnectionPurpose.Publish);
509
- logger_1.default.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
510
- throw e;
441
+ async sendToQueue(queue, content, options, customHeaders, isBlocking) {
442
+ const callback = async () => {
443
+ try {
444
+ RabbitMq.validateName('queue', queue);
445
+ await this.assertChannel();
446
+ await this.assertQueue(queue, options);
447
+ const res = await this.channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));
448
+ debug(`rabbit: sending to queue ${queue}`, { res });
449
+ return res;
450
+ }
451
+ catch (e) {
452
+ logger_1.default.error(`rabbit: failed to send to queue ${queue}`, { e });
453
+ throw e;
454
+ }
455
+ };
456
+ if (isBlocking) {
457
+ return callback();
511
458
  }
459
+ return utils_1.wrapSetImmediate(callback);
512
460
  }
513
- async isConnected(connectionPurpose) {
514
- const connection = await this.getConnection(connectionPurpose);
515
- if (!connection) {
516
- logger_1.default.error('rabbit: isConnected - false');
517
- return false;
518
- }
519
- const isConnected = connection.isConnected();
520
- if (!isConnected) {
521
- logger_1.default.error('rabbit: isConnected - false');
522
- return false;
523
- }
524
- const channel = await this.assertChannel({ connectionPurpose });
525
- try {
526
- await Promise.all([
527
- channel.waitForConnect(),
528
- ...this.consumers.map((c) => channel.checkQueue(c.queue)),
529
- ]);
530
- }
531
- catch (e) {
532
- logger_1.default.error('rabbit: isConnected - false');
533
- return false;
534
- }
535
- logger_1.default.info('rabbit: isConnected - true');
536
- return true;
461
+ async isConnected() {
462
+ const connection = await this.getConnection();
463
+ return connection.isConnected();
537
464
  }
538
465
  async gracefulShutdown(signal) {
539
466
  const tagsNumber = this.consumersTags.length;
@@ -1,4 +1,4 @@
1
- export type RedisConfig = {
1
+ export declare type RedisConfig = {
2
2
  host: string;
3
3
  port: number | undefined;
4
4
  prefix?: string;