@autofleet/rabbit 3.4.0-beta.9 → 3.5.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mock/index.ts"],"names":[],"mappings":";;AAAA,gDAAgD;AAChD,gBAAc;AAGd,MAAM,QAAQ;IAAd;QACE,QAAG,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAErB,SAAI,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAEtB,kBAAa,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAE/B,mBAAc,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAEhC,gBAAW,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAE7B,YAAO,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,wBAAmB,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAErC,YAAO,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;QAEzB,gBAAW,GAAQ,IAAI,CAAC,EAAE,EAAE,CAAC;IAC/B,CAAC;CAAA;AAED,kBAAe,QAAQ,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { IAfRabbitMq } from '../index';
2
+ declare class RabbitMq implements IAfRabbitMq {
3
+ ack: import("@vitest/spy").Mock<(...args: any[]) => any>;
4
+ nack: import("@vitest/spy").Mock<(...args: any[]) => any>;
5
+ assertChannel: import("@vitest/spy").Mock<(...args: any[]) => any>;
6
+ assertExchange: import("@vitest/spy").Mock<(...args: any[]) => any>;
7
+ assertQueue: import("@vitest/spy").Mock<(...args: any[]) => any>;
8
+ consume: import("@vitest/spy").Mock<(...args: any[]) => any>;
9
+ consumeFromExchange: import("@vitest/spy").Mock<(...args: any[]) => any>;
10
+ publish: import("@vitest/spy").Mock<(...args: any[]) => any>;
11
+ sendToQueue: import("@vitest/spy").Mock<(...args: any[]) => any>;
12
+ }
13
+ export default RabbitMq;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ class RabbitMq {
5
+ constructor() {
6
+ this.ack = vitest_1.vi.fn();
7
+ this.nack = vitest_1.vi.fn();
8
+ this.assertChannel = vitest_1.vi.fn();
9
+ this.assertExchange = vitest_1.vi.fn();
10
+ this.assertQueue = vitest_1.vi.fn();
11
+ this.consume = vitest_1.vi.fn();
12
+ this.consumeFromExchange = vitest_1.vi.fn();
13
+ this.publish = vitest_1.vi.fn();
14
+ this.sendToQueue = vitest_1.vi.fn();
15
+ }
16
+ }
17
+ exports.default = RabbitMq;
18
+ //# sourceMappingURL=vitest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitest.js","sourceRoot":"","sources":["../../src/mock/vitest.ts"],"names":[],"mappings":";;AAAA,mCAA4B;AAG5B,MAAM,QAAQ;IAAd;QACE,QAAG,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAEd,SAAI,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAEf,kBAAa,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAExB,mBAAc,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAEzB,gBAAW,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAEtB,YAAO,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAElB,wBAAmB,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAE9B,YAAO,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;QAElB,gBAAW,GAAG,WAAE,CAAC,EAAE,EAAE,CAAC;IACxB,CAAC;CAAA;AAED,kBAAe,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.4.0-beta.9",
3
+ "version": "3.5.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "engines": {
@@ -10,40 +10,47 @@
10
10
  "postinstall": "echo '\\033[0;31m\nWARNING: in case of migrating to new version of @autofleet/rabbit \nyou might have to delete existing queues or the deployment will fail.\\033[0m\n'",
11
11
  "start": "ts-node src/index.ts",
12
12
  "example": "ts-node src/example.ts",
13
- "build": "rm -rf dist && tsc",
14
- "linter": "./node_modules/.bin/eslint .",
15
- "test": "jest --runInBand --forceExit",
16
- "test-local": "RABBITMQ_SERVICE_HOST=localhost:5672 jest --forceExit",
17
- "coverage": "jest --coverage --forceExit && rm -rf ./coverage",
13
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
14
+ "linter": "eslint .",
15
+ "test": "vitest",
16
+ "test-local": "RABBITMQ_SERVICE_HOST=localhost:5672 node --inspect-brk ./node_modules/.bin/vitest --testTimeout=10000000000",
17
+ "coverage": "vitest --coverage",
18
18
  "dev": "nodemon"
19
19
  },
20
20
  "dependencies": {
21
21
  "@autofleet/zehut": "^3.1.2",
22
- "amqp-connection-manager": "4.1.9",
23
- "amqplib": "0.10.3",
22
+ "amqp-connection-manager": "4.1.14",
23
+ "amqplib": "0.10.5",
24
24
  "bluebird": "^3.7.2",
25
- "moment": "^2.29.1",
25
+ "moment": "^2.30.1",
26
26
  "redis": "^3.1.2",
27
27
  "redis-lock": "^0.1.4"
28
28
  },
29
29
  "peerDependencies": {
30
- "@autofleet/logger": "*"
30
+ "@autofleet/logger": "*",
31
+ "jest": "*"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "jest": {
35
+ "optional": true
36
+ }
31
37
  },
32
38
  "devDependencies": {
33
39
  "@autofleet/logger": "4.0.6",
34
- "@types/amqplib": "0.8.2",
40
+ "@types/amqplib": "0.10.7",
41
+ "@types/bluebird": "^3.5.42",
35
42
  "@types/jest": "^29.5.12",
36
43
  "@types/node": "^20.14.11",
37
44
  "@typescript-eslint/eslint-plugin": "^4.8.1",
45
+ "@vitest/coverage-v8": "^3.1.3",
38
46
  "eslint": "^7.13.0",
39
47
  "eslint-config-airbnb-typescript": "^12.0.0",
40
48
  "eslint-plugin-import": "^2.22.1",
41
- "jest": "^29.7.0",
42
49
  "node-tcp-proxy": "^0.0.28",
43
- "ts-jest": "^29.2.3",
44
50
  "ts-node": "^8.6.2",
45
- "typescript": "^4.9.5"
51
+ "typescript": "^4.9.5",
52
+ "vitest": "^3.1.3"
46
53
  },
47
54
  "author": "",
48
- "license": "ISC"
55
+ "license": "Proprietary"
49
56
  }
package/src/index.ts CHANGED
@@ -45,6 +45,11 @@ const debug = logger.debug.bind(logger);
45
45
 
46
46
  const PUBLISH_TIMEOUT = 1000 * 10;
47
47
 
48
+ // TODO: [QUORUM-PHASE-3] Delete this env var
49
+ const {
50
+ DISABLE_QUORUM_QUEUES,
51
+ } = process.env;
52
+
48
53
  export interface IAfRabbitMq {
49
54
  ack: any;
50
55
  nack: any;
@@ -149,8 +154,6 @@ class RabbitMq implements IAfRabbitMq {
149
154
 
150
155
  blockReconnect: boolean | null | undefined
151
156
 
152
- connection: AmqpConnectionManager | null | undefined
153
-
154
157
  publishConnection: ConnectionData
155
158
 
156
159
  consumeConnection: ConnectionData
@@ -213,16 +216,15 @@ class RabbitMq implements IAfRabbitMq {
213
216
  this.em = new EventEmitter();
214
217
  this.publishChannel = null;
215
218
  this.publishChannelSetupPromise = null;
216
- this.connection = null;
217
219
  this.publishConnection = {
218
- connection: null,
220
+ amqpConnection: null,
219
221
  creatingConnection: false,
220
222
  connectionCreatedEventName: 'publishConnectionCreated',
221
223
  connectionFailedEventName: 'publishConnectionFailed',
222
224
  blockReconnect: false,
223
225
  };
224
226
  this.consumeConnection = {
225
- connection: null,
227
+ amqpConnection: null,
226
228
  creatingConnection: false,
227
229
  connectionCreatedEventName: 'consumeConnectionCreated',
228
230
  connectionFailedEventName: 'consumeConnectionFailed',
@@ -256,14 +258,14 @@ class RabbitMq implements IAfRabbitMq {
256
258
  this.oldPublishChannel = null;
257
259
  this.oldPublishChannelSetupPromise = null;
258
260
  this.oldPublishConnection = {
259
- connection: null,
261
+ amqpConnection: null,
260
262
  creatingConnection: false,
261
263
  connectionCreatedEventName: 'oldPublishConnectionCreated',
262
264
  connectionFailedEventName: 'oldPublishConnectionFailed',
263
265
  blockReconnect: false,
264
266
  };
265
267
  this.oldConsumeConnection = {
266
- connection: null,
268
+ amqpConnection: null,
267
269
  creatingConnection: false,
268
270
  connectionCreatedEventName: 'oldConsumeConnectionCreated',
269
271
  connectionFailedEventName: 'oldConsumeConnectionFailed',
@@ -378,13 +380,13 @@ class RabbitMq implements IAfRabbitMq {
378
380
  if (
379
381
  !skipRetry
380
382
  && (
381
- !msg.properties.headers[RETRY_HEADER]
383
+ !msg.properties.headers?.[RETRY_HEADER]
382
384
  || parseInt(msg.properties.headers[RETRY_HEADER], 10) < options.retries
383
385
  )
384
386
  ) {
385
387
  await this.sendToQueue(queue, RabbitMq.parseMsg(msg).content, options, {
386
388
  ...msg.properties.headers,
387
- [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
389
+ [RETRY_HEADER]: msg.properties.headers?.[RETRY_HEADER]
388
390
  ? msg.properties.headers[RETRY_HEADER] + 1
389
391
  : 1,
390
392
  });
@@ -392,7 +394,7 @@ class RabbitMq implements IAfRabbitMq {
392
394
  const deadQueue = `${queue}-dead`;
393
395
  await this.sendToQueue(deadQueue, RabbitMq.parseMsg(msg).content, deadQueueOptions, {
394
396
  ...msg.properties.headers,
395
- [RETRY_HEADER]: msg.properties.headers[RETRY_HEADER]
397
+ [RETRY_HEADER]: msg.properties.headers?.[RETRY_HEADER]
396
398
  ? msg.properties.headers[RETRY_HEADER] + 1
397
399
  : 1,
398
400
  });
@@ -409,12 +411,13 @@ class RabbitMq implements IAfRabbitMq {
409
411
  async getConnection(connection: ConnectionData) {
410
412
  return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
411
413
  const {
412
- connection: connectionLocal,
414
+ amqpConnection: connectionLocal,
413
415
  creatingConnection,
414
416
  connectionCreatedEventName,
415
417
  connectionFailedEventName,
416
418
  blockReconnect,
417
419
  } = connection;
420
+
418
421
  if (blockReconnect) {
419
422
  debug('rabbit: block reconnect');
420
423
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -456,12 +459,7 @@ class RabbitMq implements IAfRabbitMq {
456
459
  findServers,
457
460
  });
458
461
 
459
- connection.connection = newConnection;
460
- if (connection === this.publishConnection) {
461
- debug('rabbit: publishConnection set');
462
- } else if (connection === this.consumeConnection) {
463
- debug('rabbit: consumeConnection set');
464
- }
462
+ connection.amqpConnection = newConnection;
465
463
  newConnection.on('error', (err) => {
466
464
  logger.error('rabbit: connection error', { err });
467
465
  if (!isResolved) {
@@ -473,6 +471,9 @@ class RabbitMq implements IAfRabbitMq {
473
471
 
474
472
  newConnection.on('connectFailed', (err) => {
475
473
  this.consumersTags = [];
474
+ if (typeof err.url === 'string') {
475
+ err.url = this.maskURL(err.url);
476
+ }
476
477
  logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });
477
478
  if (!isResolved) {
478
479
  isResolved = true;
@@ -496,7 +497,7 @@ class RabbitMq implements IAfRabbitMq {
496
497
  newConnection.once('connect', async () => {
497
498
  debug('rabbit: connection established');
498
499
  connection.creatingConnection = false;
499
- this.em.emit(connectionCreatedEventName, connection);
500
+ this.em.emit(connectionCreatedEventName, newConnection);
500
501
  isResolved = true;
501
502
  resolve(newConnection);
502
503
  });
@@ -576,7 +577,7 @@ class RabbitMq implements IAfRabbitMq {
576
577
  if (!channel) {
577
578
  throw new RabbitError('channel is not defined');
578
579
  }
579
- debug('rabbit: getting queue length', { queue, connected: this.connection?.isConnected() });
580
+ debug('rabbit: getting queue length', { queue, connected: this.oldPublishConnection.amqpConnection?.isConnected() });
580
581
  return channel?.checkQueue(queue);
581
582
  }
582
583
 
@@ -682,7 +683,7 @@ class RabbitMq implements IAfRabbitMq {
682
683
  // Used by the microservices to consume messages from the queue
683
684
  async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
684
685
  // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld
685
- if (options?.isQuorumQueue !== false) {
686
+ if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES !== 'true') {
686
687
  await this.assertVHost();
687
688
  await this.consumeNew(queue, callback, options);
688
689
  }
@@ -745,9 +746,9 @@ class RabbitMq implements IAfRabbitMq {
745
746
  return null;
746
747
  }
747
748
 
748
- const traceId = msg.properties.headers[TRACING_HEADER];
749
- const userId = msg.properties.headers[USER_TRACING_HEADER];
750
- const automationId = msg.properties.headers[AUTOMATION_ID_HEADER];
749
+ const traceId = msg.properties.headers![TRACING_HEADER];
750
+ const userId = msg.properties.headers![USER_TRACING_HEADER];
751
+ const automationId = msg.properties.headers![AUTOMATION_ID_HEADER];
751
752
  const parsedMessage = RabbitMq.parseMsg(msg);
752
753
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
753
754
  const trace = newTrace(traceTypes.RABBIT);
@@ -831,7 +832,7 @@ class RabbitMq implements IAfRabbitMq {
831
832
  RabbitMq.validateName('queue', queue);
832
833
  const { limit, deadMessageTtl } = optionsWithDefaults;
833
834
  // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues
834
- if (options?.isQuorumQueue !== false) {
835
+ if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES !== 'true') {
835
836
  await this.assertVHost();
836
837
  await this.saveConsumer(queue, callback, options);
837
838
  const channel: ChannelWrapper = await this.getNewChannel({
@@ -853,28 +854,27 @@ class RabbitMq implements IAfRabbitMq {
853
854
  ),
854
855
  ]);
855
856
  });
856
- } else {
857
- // TODO: [QUORUM-PHASE-3] Delete the old implementation
858
- await this.saveConsumerOld(queue, callback, options);
859
- const channelOld: ChannelWrapper = await this.getNewChannelOld({
860
- name: `consume-exchange-${exchange}-queue-${queue}-old`,
861
- connection: this.oldConsumeConnection,
862
- });
863
- await channelOld.addSetup(async (c: ConfirmChannel) => {
864
- const assertExchange = await assertExchangeFanout(c, exchange);
865
- await c.assertQueue(queue);
866
- this.oldExchanges[exchange] = assertExchange;
867
- await c.prefetch(limit, false);
868
- return Promise.all([
869
- c.bindQueue(queue, exchange, ''),
870
- this.consumeOld(
871
- queue,
872
- callback,
873
- options,
874
- ),
875
- ]);
876
- });
877
857
  }
858
+ // TODO: [QUORUM-PHASE-3] Delete the old implementation
859
+ await this.saveConsumerOld(queue, callback, options);
860
+ const channelOld: ChannelWrapper = await this.getNewChannelOld({
861
+ name: `consume-exchange-${exchange}-queue-${queue}-old`,
862
+ connection: this.oldConsumeConnection,
863
+ });
864
+ await channelOld.addSetup(async (c: ConfirmChannel) => {
865
+ const assertExchange = await assertExchangeFanout(c, exchange);
866
+ await c.assertQueue(queue);
867
+ this.oldExchanges[exchange] = assertExchange;
868
+ await c.prefetch(limit, false);
869
+ return Promise.all([
870
+ c.bindQueue(queue, exchange, ''),
871
+ this.consumeOld(
872
+ queue,
873
+ callback,
874
+ options,
875
+ ),
876
+ ]);
877
+ });
878
878
  }
879
879
 
880
880
  // Used by the microservices to publish messages to the exchange
@@ -920,53 +920,71 @@ class RabbitMq implements IAfRabbitMq {
920
920
  debug(`rabbit: sending to queue ${queue}`, { res });
921
921
  return res;
922
922
  } catch (e) {
923
- const isConnected = await this.isConnected();
923
+ const isConnected = await this.isConnectedOld();
924
924
  logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });
925
925
  throw e;
926
926
  }
927
927
  }
928
928
 
929
929
  // TODO: [QUORUM-PHASE-2] After changing the publish from old to new change from the old to the new implementation
930
- async isConnected() : Promise<boolean> {
931
- debug('rabbit: start old is connected');
932
- const oldConsumeConnection = await this.getConnectionOld(this.oldConsumeConnection);
933
- const oldPublishConnection = await this.getConnectionOld(this.oldPublishConnection);
934
- const oldIsConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();
935
- if (!oldIsConnected) {
936
- logger.error('rabbit: isConnected - false');
930
+ async isConnected(): Promise<boolean> {
931
+ const [connectionNew, connectionOld] = await Promise.all([
932
+ this.isConnectedNew(),
933
+ this.isConnectedOld(),
934
+ ]);
935
+
936
+ return connectionNew && connectionOld;
937
+ }
938
+
939
+ // TODO: [QUORUM-PHASE-2] After changing the publish from old to new change from the old to the new implementation
940
+ async isConnectedNew(): Promise<boolean> {
941
+ if (DISABLE_QUORUM_QUEUES === 'true') {
942
+ return true;
943
+ }
944
+
945
+ debug('rabbit: start new is connected');
946
+ const consumeConnection = await this.getConnection(this.consumeConnection);
947
+ const publishConnection = await this.getConnection(this.publishConnection);
948
+ const isConnected = consumeConnection.isConnected() && publishConnection.isConnected();
949
+ if (!isConnected) {
950
+ logger.error('rabbit: new isConnected - false');
937
951
  return false;
938
952
  }
939
- const oldChannel: any = await this.assertChannelOld({ connection: this.oldPublishConnection });
953
+ const channel: any = await this.assertChannel({ connection: this.publishConnection });
940
954
  try {
941
955
  await Promise.all([
942
- oldChannel.waitForConnect(),
943
- ...this.oldConsumers.map((c: AfConsumer) => oldChannel.checkQueue(c.queue)),
956
+ channel.waitForConnect(),
957
+ ...this.consumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
944
958
  ]);
945
959
  } catch (e) {
946
- logger.error('rabbit: isConnected - false');
960
+ logger.error('rabbit: new isConnected - false');
947
961
  return false;
948
962
  }
949
- logger.debug('rabbit: old isConnected - true');
963
+ logger.debug('rabbit: new isConnected - true');
964
+ return true;
965
+ }
950
966
 
951
- debug('rabbit: start is connected');
952
- const consumeConnection = await this.getConnectionOld(this.oldConsumeConnection);
953
- const publishConnection = await this.getConnectionOld(this.oldPublishConnection);
954
- const isConnected = consumeConnection.isConnected() && publishConnection.isConnected();
955
- if (!isConnected) {
956
- logger.error('rabbit: isConnected - false');
967
+ // TODO: [QUORUM-PHASE-2] After changing the publish from old to new change from the old to the new implementation
968
+ async isConnectedOld(): Promise<boolean> {
969
+ debug('rabbit: start old is connected');
970
+ const oldConsumeConnection = await this.getConnectionOld(this.oldConsumeConnection);
971
+ const oldPublishConnection = await this.getConnectionOld(this.oldPublishConnection);
972
+ const oldIsConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();
973
+ if (!oldIsConnected) {
974
+ logger.error('rabbit: old isConnected - false');
957
975
  return false;
958
976
  }
959
- const channel: any = await this.assertChannelOld({ connection: this.oldPublishConnection });
977
+ const oldChannel: any = await this.assertChannelOld({ connection: this.oldPublishConnection });
960
978
  try {
961
979
  await Promise.all([
962
- channel.waitForConnect(),
963
- ...this.oldConsumers.map((c: AfConsumer) => channel.checkQueue(c.queue)),
980
+ oldChannel.waitForConnect(),
981
+ ...this.oldConsumers.map((c: AfConsumer) => oldChannel.checkQueue(c.queue)),
964
982
  ]);
965
983
  } catch (e) {
966
- logger.error('rabbit: isConnected - false');
984
+ logger.error('rabbit: old isConnected - false');
967
985
  return false;
968
986
  }
969
- logger.debug('rabbit: isConnected - true');
987
+ logger.debug('rabbit: old isConnected - true');
970
988
  return true;
971
989
  }
972
990
 
@@ -990,7 +1008,6 @@ class RabbitMq implements IAfRabbitMq {
990
1008
 
991
1009
  private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any> {
992
1010
  const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };
993
- debug('rabbit: consumeFromRabbitOld', { queue });
994
1011
  RabbitMq.validateName('queue', queue);
995
1012
  this.saveConsumerOld(queue, callback, options);
996
1013
  const uniqueId = randomUUID();
@@ -1014,9 +1031,9 @@ class RabbitMq implements IAfRabbitMq {
1014
1031
  return null;
1015
1032
  }
1016
1033
 
1017
- const traceId = msg.properties.headers[TRACING_HEADER];
1018
- const userId = msg.properties.headers[USER_TRACING_HEADER];
1019
- const automationId = msg.properties.headers[AUTOMATION_ID_HEADER];
1034
+ const traceId = msg.properties.headers![TRACING_HEADER];
1035
+ const userId = msg.properties.headers![USER_TRACING_HEADER];
1036
+ const automationId = msg.properties.headers![AUTOMATION_ID_HEADER];
1020
1037
  const parsedMessage = RabbitMq.parseMsg(msg);
1021
1038
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
1022
1039
  const trace = newTrace(traceTypes.RABBIT);
@@ -1098,11 +1115,6 @@ class RabbitMq implements IAfRabbitMq {
1098
1115
  name = rand().toString(), onClose = null, options = {}, connection,
1099
1116
  }: newChannelOpts) {
1100
1117
  let localConnection!: AmqpConnectionManager;
1101
- if (connection === this.oldPublishConnection) {
1102
- debug('rabbit: getConnectionOld publish', { connection });
1103
- } else if (connection === this.oldConsumeConnection) {
1104
- debug('rabbit: getConnectionOld consume', { connection });
1105
- }
1106
1118
  try {
1107
1119
  localConnection = await this.getConnectionOld(connection);
1108
1120
  } catch (e) {
@@ -1114,7 +1126,6 @@ class RabbitMq implements IAfRabbitMq {
1114
1126
  throw new Error(`rabbit: couldnt get connection for new channel ${name}`);
1115
1127
  }
1116
1128
 
1117
- debug('rabbit: getNewChannelOld', { localConnection });
1118
1129
  const channel = localConnection?.createChannel({ ...options });
1119
1130
  once(channel, 'close').then((args) => {
1120
1131
  logger.error(`rabbit: channel ${name} closed`);
@@ -1133,18 +1144,13 @@ class RabbitMq implements IAfRabbitMq {
1133
1144
  async getConnectionOld(connection: ConnectionData) {
1134
1145
  return new Promise<AmqpConnectionManager>(async (resolve, reject) => {
1135
1146
  const {
1136
- connection: connectionLocal,
1147
+ amqpConnection: connectionLocal,
1137
1148
  creatingConnection,
1138
1149
  connectionCreatedEventName,
1139
1150
  connectionFailedEventName,
1140
1151
  blockReconnect,
1141
1152
  } = connection;
1142
1153
 
1143
- if (connection === this.oldPublishConnection) {
1144
- debug('rabbit: getConnectionOld publish', { connectionLocal, creatingConnection, blockReconnect });
1145
- } else if (connection === this.oldConsumeConnection) {
1146
- debug('rabbit: getConnectionOld consume', { connectionLocal, creatingConnection, blockReconnect });
1147
- }
1148
1154
  if (blockReconnect) {
1149
1155
  debug('rabbit: block reconnect');
1150
1156
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -1187,12 +1193,7 @@ class RabbitMq implements IAfRabbitMq {
1187
1193
  findServers,
1188
1194
  });
1189
1195
 
1190
- connection.connection = newConnection;
1191
- if (connection === this.oldPublishConnection) {
1192
- debug('rabbit: oldPublishConnection set');
1193
- } else if (connection === this.oldConsumeConnection) {
1194
- debug('rabbit: oldConsumeConnection set');
1195
- }
1196
+ connection.amqpConnection = newConnection;
1196
1197
  newConnection.on('error', (err) => {
1197
1198
  logger.error('rabbit: connection error', { err });
1198
1199
  if (!isResolved) {
@@ -1204,6 +1205,9 @@ class RabbitMq implements IAfRabbitMq {
1204
1205
 
1205
1206
  newConnection.on('connectFailed', (err) => {
1206
1207
  this.oldConsumersTags = [];
1208
+ if (typeof err.url === 'string') {
1209
+ err.url = this.maskURL(err.url);
1210
+ }
1207
1211
  logger.error('rabbit: connection connectFailed', { err });
1208
1212
  if (!isResolved) {
1209
1213
  isResolved = true;
@@ -1226,7 +1230,7 @@ class RabbitMq implements IAfRabbitMq {
1226
1230
  newConnection.once('connect', async () => {
1227
1231
  debug('rabbit: connection established');
1228
1232
  connection.creatingConnection = false;
1229
- this.oldEm.emit(connectionCreatedEventName, connection);
1233
+ this.oldEm.emit(connectionCreatedEventName, newConnection);
1230
1234
  isResolved = true;
1231
1235
  resolve(newConnection);
1232
1236
  });
@@ -1300,11 +1304,6 @@ class RabbitMq implements IAfRabbitMq {
1300
1304
  }
1301
1305
 
1302
1306
  async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {
1303
- if (connection === this.oldPublishConnection) {
1304
- debug('rabbit: assertChannelOld publish', { force, promiseSetup: this.oldPublishChannelSetupPromise });
1305
- } else if (connection === this.oldConsumeConnection) {
1306
- debug('rabbit: assertChannelOld consume', { force, promiseSetup: this.oldPublishChannelSetupPromise });
1307
- }
1308
1307
  if (!this.oldPublishChannelSetupPromise) {
1309
1308
  this.oldPublishChannelSetupPromise = new Promise<ChannelWrapper>(async (resolve, reject) => {
1310
1309
  if (this.oldPublishChannel && !force) {
@@ -1313,16 +1312,10 @@ class RabbitMq implements IAfRabbitMq {
1313
1312
 
1314
1313
  try {
1315
1314
  const channel = await this.getNewChannelOld({ connection });
1316
- if (connection === this.oldPublishConnection) {
1317
- debug('rabbit: old new channel got publish', { force, channel });
1318
- } else if (connection === this.oldConsumeConnection) {
1319
- debug('rabbit: old new channel got consume', { force, channel });
1320
- }
1321
1315
  channel.on('error', (err) => {
1322
1316
  logger.error('rabbit: channel error', { err });
1323
1317
  });
1324
1318
  if (this.oldPublishConnection === connection) {
1325
- debug('rabbit: a new channel assigned to the oldPublishChannel', { connection });
1326
1319
  this.oldPublishChannel = channel;
1327
1320
  }
1328
1321
  resolve(channel);
@@ -1359,6 +1352,17 @@ class RabbitMq implements IAfRabbitMq {
1359
1352
  this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];
1360
1353
  return this.oldExchanges[exchangeName];
1361
1354
  }
1355
+
1356
+ private maskURL = (url: string): string => {
1357
+ try {
1358
+ const urlObj = new URL(url);
1359
+ urlObj.username = '***';
1360
+ urlObj.password = '***';
1361
+ return urlObj.toString();
1362
+ } catch {
1363
+ return url;
1364
+ }
1365
+ }
1362
1366
  }
1363
1367
 
1364
1368
  export default RabbitMq;
package/src/lib/types.ts CHANGED
@@ -64,7 +64,7 @@ export const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {
64
64
  };
65
65
 
66
66
  export type ConnectionData = {
67
- connection: AmqpConnectionManager | null;
67
+ amqpConnection: AmqpConnectionManager | null;
68
68
  creatingConnection: boolean;
69
69
  connectionCreatedEventName: string;
70
70
  connectionFailedEventName: string;
@@ -1,6 +1,6 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
1
+ // eslint-disable-next-line import/no-unresolved
2
2
  import 'jest';
3
- import { IAfRabbitMq } from './index';
3
+ import type { IAfRabbitMq } from '../index';
4
4
 
5
5
  class RabbitMq implements IAfRabbitMq {
6
6
  ack: any = jest.fn();
@@ -0,0 +1,24 @@
1
+ import { vi } from 'vitest';
2
+ import { IAfRabbitMq } from '../index';
3
+
4
+ class RabbitMq implements IAfRabbitMq {
5
+ ack = vi.fn();
6
+
7
+ nack = vi.fn();
8
+
9
+ assertChannel = vi.fn();
10
+
11
+ assertExchange = vi.fn();
12
+
13
+ assertQueue = vi.fn();
14
+
15
+ consume = vi.fn();
16
+
17
+ consumeFromExchange = vi.fn();
18
+
19
+ publish = vi.fn();
20
+
21
+ sendToQueue = vi.fn();
22
+ }
23
+
24
+ export default RabbitMq;
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": ["src"],
4
+ "exclude": ["node_modules", "dist", "src/example.ts", "**/*.test.ts"],
5
+ }
package/tsconfig.json CHANGED
@@ -9,8 +9,8 @@
9
9
  "experimentalDecorators": true,
10
10
  "emitDecoratorMetadata": true,
11
11
  "skipLibCheck": true,
12
- "types": ["@types/jest"]
12
+ "sourceMap": true,
13
13
  },
14
14
  "exclude": ["node_modules"],
15
- "include": ["src/**/*.ts"]
15
+ "include": ["src/", "vitest.config.ts"],
16
16
  }
@@ -0,0 +1,16 @@
1
+ // eslint-disable-next-line import/no-unresolved
2
+ import { defineConfig } from 'vitest/config';
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ coverage: {
7
+ provider: 'v8',
8
+ include: ['src/**/*.ts'],
9
+ exclude: ['src/example.ts', 'src/mock/*.ts'],
10
+ reporter: 'text',
11
+ thresholds: {
12
+ lines: 74,
13
+ },
14
+ },
15
+ },
16
+ });