@autofleet/rabbit 3.2.21-beta.0.6 → 3.2.21

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 CHANGED
@@ -4,7 +4,6 @@ import { AmqpConnectionManager, ChannelWrapper, CreateChannelOpts } from 'amqp-c
4
4
  import { ConfirmChannel, ConsumeMessage, Options, Replies } from 'amqplib';
5
5
  import { RedisConfig } from './lib/redis';
6
6
  import { CallbackFunction, ConsumeMessageOrNull, ConsumeOptions, CustomMessageHeaders, QueuesCache, RedisLockType, ExchangesCache, QueueSetupPromisesDictionary, AssertExchangePromisesDictionary } from './lib/types';
7
- import { sendCeleryTaskViaHttp } from './lib/celery';
8
7
  export interface IAfRabbitMq {
9
8
  ack: any;
10
9
  nack: any;
@@ -86,6 +85,7 @@ declare class RabbitMq implements IAfRabbitMq {
86
85
  private deleteQueue;
87
86
  bindQueue(queue: string, exchange: string): Promise<void>;
88
87
  setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue>;
88
+ static shouldUseQuorum(queueName: string): boolean;
89
89
  assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any>;
90
90
  private saveConsumer;
91
91
  consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<any>;
@@ -99,4 +99,3 @@ declare class RabbitMq implements IAfRabbitMq {
99
99
  gracefulShutdown(signal: string): Promise<void>;
100
100
  }
101
101
  export default RabbitMq;
102
- export { sendCeleryTaskViaHttp, };
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.sendCeleryTaskViaHttp = void 0;
8
7
  const events_1 = require("events");
9
8
  const util_1 = require("util");
10
9
  const moment_1 = __importDefault(require("moment"));
@@ -18,8 +17,6 @@ const redis_1 = __importDefault(require("./lib/redis"));
18
17
  const utils_1 = require("./lib/utils");
19
18
  const consts_1 = require("./lib/consts");
20
19
  const types_1 = require("./lib/types");
21
- const celery_1 = require("./lib/celery");
22
- Object.defineProperty(exports, "sendCeleryTaskViaHttp", { enumerable: true, get: function () { return celery_1.sendCeleryTaskViaHttp; } });
23
20
  // const debug = nodeDebug('af-rabbitmq')
24
21
  const debug = logger_1.default.debug.bind(logger_1.default);
25
22
  const PUBLISH_TIMEOUT = 1000 * 10;
@@ -304,12 +301,22 @@ class RabbitMq {
304
301
  }
305
302
  async setupQueue(queueName, options) {
306
303
  let queue;
304
+ const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
305
+ const localeOptions = {
306
+ ...options,
307
+ durable: true,
308
+ arguments: {
309
+ ...options?.arguments,
310
+ 'x-consumer-timeout': 1000 * 60 * 60 * 24,
311
+ 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',
312
+ },
313
+ };
307
314
  try {
308
315
  const channel = await this.assertChannel();
309
316
  debug('assertQueue->channel.addSetup', { queueName });
310
- await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
317
+ await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
311
318
  debug('assertQueue->channel.assertQueue', { queueName });
312
- queue = await channel.assertQueue(queueName, options);
319
+ queue = await channel.assertQueue(queueName, localeOptions);
313
320
  }
314
321
  catch (e) {
315
322
  logger_1.default.error('rabbit: assertQueue error', { queueName, options, error: e });
@@ -318,17 +325,28 @@ class RabbitMq {
318
325
  const channel = await this.assertChannel({ force: true });
319
326
  await this.deleteQueue(queueName);
320
327
  debug('retrying assertQueue->channel.addSetup', { queueName });
321
- await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, options));
328
+ await channel.addSetup((setupChannel) => setupChannel.assertQueue(queueName, localeOptions));
322
329
  debug('retrying assertQueue->channel.assertQueue', { queueName });
323
- queue = await channel.assertQueue(queueName, options);
330
+ queue = await channel.assertQueue(queueName, localeOptions);
324
331
  }
325
332
  else {
326
333
  throw e;
327
334
  }
328
335
  }
329
- this.queues[queueName] = queueName;
336
+ this.queues[queueName] = queue;
330
337
  return queue;
331
338
  }
339
+ static shouldUseQuorum(queueName) {
340
+ const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;
341
+ if (envQuorumQueuesWhitelist === '*') {
342
+ return true;
343
+ }
344
+ if (envQuorumQueuesWhitelist) {
345
+ const whitelist = envQuorumQueuesWhitelist.split(',');
346
+ return whitelist.includes(queueName);
347
+ }
348
+ return false;
349
+ }
332
350
  async assertQueue(queueName, options) {
333
351
  RabbitMq.validateName('queue', queueName);
334
352
  if (this.queues[queueName]) {
@@ -383,8 +401,8 @@ class RabbitMq {
383
401
  }
384
402
  const channel = await this.getNewChannel({});
385
403
  return channel.addSetup(async (confirmChannel) => {
386
- await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
387
- await confirmChannel.prefetch(limit, true);
404
+ const q = await this.assertQueue(queue, optionsWithDefaults);
405
+ await confirmChannel.prefetch(limit, false);
388
406
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
389
407
  if (!msg) {
390
408
  return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "3.2.21-beta.0.6",
3
+ "version": "3.2.21",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -43,4 +43,4 @@
43
43
  },
44
44
  "author": "",
45
45
  "license": "ISC"
46
- }
46
+ }
package/src/index.ts CHANGED
@@ -41,8 +41,6 @@ import {
41
41
  AssertExchangePromisesDictionary,
42
42
  } from './lib/types';
43
43
 
44
- import { sendCeleryTaskViaHttp } from './lib/celery';
45
-
46
44
  // const debug = nodeDebug('af-rabbitmq')
47
45
  const debug = logger.debug.bind(logger);
48
46
 
@@ -453,12 +451,22 @@ class RabbitMq implements IAfRabbitMq {
453
451
 
454
452
  async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {
455
453
  let queue: Replies.AssertQueue;
454
+ const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);
455
+ const localeOptions = {
456
+ ...options,
457
+ durable: true,
458
+ arguments: {
459
+ ...options?.arguments,
460
+ 'x-consumer-timeout': 1000 * 60 * 60 * 24,
461
+ 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',
462
+ },
463
+ };
456
464
  try {
457
465
  const channel: ChannelWrapper = await this.assertChannel();
458
466
  debug('assertQueue->channel.addSetup', { queueName });
459
- await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
467
+ await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
460
468
  debug('assertQueue->channel.assertQueue', { queueName });
461
- queue = await channel.assertQueue(queueName, options);
469
+ queue = await channel.assertQueue(queueName, localeOptions);
462
470
  } catch (e) {
463
471
  logger.error('rabbit: assertQueue error', { queueName, options, error: e });
464
472
  if (!this.options?.dontRetryAssert) {
@@ -467,19 +475,34 @@ class RabbitMq implements IAfRabbitMq {
467
475
  await this.deleteQueue(queueName);
468
476
 
469
477
  debug('retrying assertQueue->channel.addSetup', { queueName });
470
- await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, options));
478
+ await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));
471
479
  debug('retrying assertQueue->channel.assertQueue', { queueName });
472
- queue = await channel.assertQueue(queueName, options);
480
+ queue = await channel.assertQueue(queueName, localeOptions);
473
481
  } else {
474
482
  throw e;
475
483
  }
476
484
  }
477
485
 
478
- this.queues[queueName] = queueName;
486
+ this.queues[queueName] = queue;
479
487
  return queue;
480
488
  }
481
489
 
482
- async assertQueue(queueName: string, options?: Options.AssertQueue) {
490
+ static shouldUseQuorum(queueName: string): boolean {
491
+ const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;
492
+
493
+ if (envQuorumQueuesWhitelist === '*') {
494
+ return true;
495
+ }
496
+
497
+ if (envQuorumQueuesWhitelist) {
498
+ const whitelist = envQuorumQueuesWhitelist.split(',');
499
+ return whitelist.includes(queueName);
500
+ }
501
+
502
+ return false;
503
+ }
504
+
505
+ async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<any> {
483
506
  RabbitMq.validateName('queue', queueName);
484
507
  if (this.queues[queueName]) {
485
508
  delete this.queueSetupPromises[queueName];
@@ -546,8 +569,8 @@ class RabbitMq implements IAfRabbitMq {
546
569
  }
547
570
  const channel = await this.getNewChannel({});
548
571
  return channel.addSetup(async (confirmChannel: ConfirmChannel) => {
549
- await confirmChannel.assertQueue(queue, options ? { messageTtl: options.messageTtl } : undefined);
550
- await confirmChannel.prefetch(limit, true);
572
+ const q = await this.assertQueue(queue, optionsWithDefaults);
573
+ await confirmChannel.prefetch(limit, false);
551
574
  const { consumerTag } = await confirmChannel.consume(
552
575
  queue,
553
576
  async (msg: ConsumeMessageOrNull) => {
@@ -737,7 +760,3 @@ class RabbitMq implements IAfRabbitMq {
737
760
  }
738
761
 
739
762
  export default RabbitMq;
740
-
741
- export {
742
- sendCeleryTaskViaHttp,
743
- };
@@ -1,9 +0,0 @@
1
- interface TaskData {
2
- [key: string]: any;
3
- }
4
- interface SendTaskOptions {
5
- taskName: string;
6
- queueName: string;
7
- }
8
- declare function sendCeleryTaskViaHttp(data: TaskData, { taskName, queueName }: SendTaskOptions): Promise<void>;
9
- export { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };
@@ -1,54 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sendCeleryTaskViaHttp = void 0;
7
- const node_crypto_1 = require("node:crypto");
8
- const logger_1 = __importDefault(require("../logger"));
9
- // Environment configuration
10
- const config = {
11
- host: process.env.RABBITMQ_SERVICE_HOST || '10.132.15.204',
12
- username: process.env.RABBITMQ_USERNAME || 'default_user_Zjlb8cnBF-jwc61bbC8',
13
- password: process.env.RABBITMQ_PASSWORD || 'SDjnZWKAgz9TROLDV85OUZb6FOLlfw1b',
14
- };
15
- async function sendCeleryTaskViaHttp(data, { taskName, queueName }) {
16
- const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;
17
- const message = {
18
- task: taskName,
19
- id: (0, node_crypto_1.randomUUID)(),
20
- args: [data],
21
- };
22
- const payload = {
23
- properties: {
24
- delivery_mode: 2,
25
- content_type: 'application/json',
26
- },
27
- routing_key: queueName,
28
- payload: JSON.stringify(message),
29
- payload_encoding: 'string',
30
- };
31
- try {
32
- const response = await fetch(apiUrl, {
33
- method: 'POST',
34
- headers: {
35
- 'Content-Type': 'application/json',
36
- Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,
37
- },
38
- body: JSON.stringify(payload),
39
- });
40
- if (response.ok) {
41
- const result = await response.json();
42
- logger_1.default.info('Successfully published message:', result);
43
- }
44
- else {
45
- logger_1.default.error(`Failed to publish message. Status code: ${response.status}`);
46
- logger_1.default.error(`Response: ${await response.text()}`);
47
- }
48
- }
49
- catch (error) {
50
- logger_1.default.error('Error sending request:', error instanceof Error ? error.message : String(error));
51
- throw error;
52
- }
53
- }
54
- exports.sendCeleryTaskViaHttp = sendCeleryTaskViaHttp;
package/src/lib/celery.ts DELETED
@@ -1,85 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
- import logger from '../logger';
3
- // Environment configuration
4
- const config = {
5
- host: process.env.RABBITMQ_SERVICE_HOST || '10.132.15.204',
6
- username: process.env.RABBITMQ_USERNAME || 'default_user_Zjlb8cnBF-jwc61bbC8',
7
- password: process.env.RABBITMQ_PASSWORD || 'SDjnZWKAgz9TROLDV85OUZb6FOLlfw1b',
8
- };
9
-
10
- // Type definitions
11
- interface TaskData {
12
- [key: string]: any;
13
- }
14
-
15
- interface TaskMessage {
16
- task: string;
17
- id: string;
18
- args: TaskData[];
19
- }
20
-
21
- interface PublishPayload {
22
- properties: {
23
- delivery_mode: number;
24
- content_type: string;
25
- };
26
- routing_key: string;
27
- payload: string;
28
- payload_encoding: string;
29
- }
30
-
31
- interface PublishResponse {
32
- routed: boolean;
33
- }
34
-
35
- interface SendTaskOptions {
36
- taskName: string;
37
- queueName: string;
38
- }
39
-
40
- async function sendCeleryTaskViaHttp(
41
- data: TaskData,
42
- { taskName, queueName }: SendTaskOptions,
43
- ): Promise<void> {
44
- const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;
45
-
46
- const message: TaskMessage = {
47
- task: taskName,
48
- id: randomUUID(),
49
- args: [data],
50
- };
51
-
52
- const payload: PublishPayload = {
53
- properties: {
54
- delivery_mode: 2,
55
- content_type: 'application/json',
56
- },
57
- routing_key: queueName,
58
- payload: JSON.stringify(message),
59
- payload_encoding: 'string',
60
- };
61
-
62
- try {
63
- const response = await fetch(apiUrl, {
64
- method: 'POST',
65
- headers: {
66
- 'Content-Type': 'application/json',
67
- Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,
68
- },
69
- body: JSON.stringify(payload),
70
- });
71
-
72
- if (response.ok) {
73
- const result: PublishResponse = await response.json();
74
- logger.info('Successfully published message:', result);
75
- } else {
76
- logger.error(`Failed to publish message. Status code: ${response.status}`);
77
- logger.error(`Response: ${await response.text()}`);
78
- }
79
- } catch (error) {
80
- logger.error('Error sending request:', error instanceof Error ? error.message : String(error));
81
- throw error;
82
- }
83
- }
84
-
85
- export { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };