@autofleet/rabbit 5.0.0 → 5.0.1

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/README.md CHANGED
@@ -5,4 +5,4 @@ The required version of zehut is now `^4.0.0`.
5
5
 
6
6
  This was moved to being a peer-dependency in order to ensure that the version of `zehut` used here is the same as used in the MS, and not risk the package using v4 while the service is using v3, which would cause `zehut` to have multiple traces, which will not all hold the correct data.
7
7
 
8
- Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
8
+ Additionally, the minimum node version is now 18, due to the minimum version of node defined in `zehut`.
package/dist/index.cjs CHANGED
@@ -165,6 +165,7 @@ var RabbitMq = class RabbitMq {
165
165
  creationTimestamp: (0, moment.default)().valueOf(),
166
166
  ...customHeaders,
167
167
  [USER_TRACING_HEADER]: user?.id,
168
+ [__autofleet_zehut.CONTEXTS_IDS_HEADER]: user?.contextIds,
168
169
  [TRACING_HEADER]: traceId
169
170
  }
170
171
  };
@@ -602,12 +603,12 @@ var RabbitMq = class RabbitMq {
602
603
  await confirmChannel.prefetch(limit, false);
603
604
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
604
605
  if (!msg) return null;
605
- const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};
606
+ const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [__autofleet_zehut.CONTEXTS_IDS_HEADER]: userContextIds } = msg.properties.headers || {};
606
607
  const parsedMessage = RabbitMq.parseMsg(msg);
607
608
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
608
609
  const trace = (0, __autofleet_zehut.newTrace)(__autofleet_zehut.traceTypes.RABBIT);
609
610
  if (userId && enableRabbitTrace) try {
610
- await (0, __autofleet_zehut.createOrSetRabbitTrace)(trace, userId);
611
+ await (0, __autofleet_zehut.createOrSetRabbitTrace)(trace, userId, userContextIds);
611
612
  } catch (e) {
612
613
  this.#logger.error("rabbit: failed to setRabbitTrace", {
613
614
  userId,
@@ -824,12 +825,12 @@ var RabbitMq = class RabbitMq {
824
825
  await confirmChannel.prefetch(limit, false);
825
826
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
826
827
  if (!msg) return null;
827
- const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};
828
+ const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [__autofleet_zehut.CONTEXTS_IDS_HEADER]: userContextIds } = msg.properties.headers || {};
828
829
  const parsedMessage = RabbitMq.parseMsg(msg);
829
830
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
830
831
  const trace = (0, __autofleet_zehut.newTrace)(__autofleet_zehut.traceTypes.RABBIT);
831
832
  if (userId && enableRabbitTrace) try {
832
- await (0, __autofleet_zehut.createOrSetRabbitTrace)(trace, userId);
833
+ await (0, __autofleet_zehut.createOrSetRabbitTrace)(trace, userId, userContextIds);
833
834
  } catch (e) {
834
835
  this.#logger.error("rabbit: failed to setRabbitTrace", {
835
836
  userId,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["logger: LoggerInstanceManager","message: string","config: RedisConfig","config","DEFAULT_DEAD_TTL_TWO_DAYS: number","DEFAULT_LOCK_TIMEOUT: number","DEFAULT_OPTIONS: ConsumeOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions","c: ChannelWrapper | ConfirmChannel","exchangeName: string","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","data: TaskData","message: TaskMessage","payload: PublishPayload","result: PublishResponse","logger","env","msg: ConsumeMessage","type: string","name: string","customHeaders: CustomMessageHeaders","outbreak","EventEmitter","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","fallbackLogger","getRedisInstance","key: string","msg: ConsumeMessageOrNull","channel: ConfirmChannel","releaseLock: (() => Promise<void>) | null","userMsg: ConsumeMessage","queue: string","options: ConsumeOptions","deadQueueOptions: Options.AssertQueue","releaseLock?: (() => Promise<void>) | null","userMsg: ConsumeMessageOrNull","connection: ConnectionData","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","exchangeName: string","channel: ChannelWrapper","exchange: string","setupChannel: ConfirmChannel","queueName: string","options?: Options.AssertQueue","queue: Replies.AssertQueue","callback: CallbackFunction","options: ConsumeOptions | undefined","isConsumerExist: boolean","options?: ConsumeOptions","msg: ReturnType<typeof RabbitMq.parseMsg>","confirmChannel: ConfirmChannel","traceTypes","_: ConsumeMessageOrNull","nackOptions: NackOptions","c: ConfirmChannel","channelOld: ChannelWrapper","content: any","customHeaders?: PublishOptions['headers']","channel","e: RabbitError | any","signal: string","url: string"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.ts","../src/lib/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport type RedisConfig = {\n host: string;\n port: number | undefined;\n prefix?: string;\n}\n\nconst getRedisInstance = (config: RedisConfig): ReturnType<typeof createClient> => createClient({ socket: config });\n\nexport default getRedisInstance;\n","import type { BackoffOptions } from 'exponential-backoff';\nimport type { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport interface ExchangesCache {\n [key: string]: Replies.AssertExchange | undefined;\n}\n\nexport interface QueuesCache {\n [key: string]: Replies.AssertQueue | undefined;\n}\n\nexport interface QueueSetupPromisesDictionary {\n [key: string]: Promise<Replies.AssertQueue> | undefined;\n}\n\nexport interface AssertExchangePromisesDictionary {\n [key: string]: Promise<Replies.AssertExchange> | undefined;\n}\n\nexport type CustomMessageHeaders = {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n // TODO: [QUORUM-PHASE-3] Redundant because all the queues are quorum queues\n isQuorumQueue?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport type newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport type assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n}\nexport type AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport type ConnectionData = {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n};\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\ninterface TaskData {\n [key: string]: any;\n}\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n // eslint-disable-next-line camelcase\n delivery_mode: number;\n // eslint-disable-next-line camelcase\n content_type: string;\n };\n // eslint-disable-next-line camelcase\n routing_key: string;\n payload: string;\n // eslint-disable-next-line camelcase\n payload_encoding: string;\n}\n\ninterface PublishResponse {\n routed: boolean;\n}\n\ninterface SendTaskOptions {\n taskName: string;\n queueName: string;\n}\n\nasync function sendCeleryTaskViaHttp(\n data: TaskData,\n { taskName, queueName }: SendTaskOptions,\n): Promise<void> {\n const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;\n\n const message: TaskMessage = {\n task: taskName,\n id: randomUUID(),\n args: [data],\n };\n\n const payload: PublishPayload = {\n properties: {\n delivery_mode: 2,\n content_type: 'application/json',\n },\n routing_key: queueName,\n payload: JSON.stringify(message),\n payload_encoding: 'string',\n };\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,\n },\n body: JSON.stringify(payload),\n });\n\n if (response.ok) {\n const result: PublishResponse = await response.json();\n logger.info('Successfully published message:', result);\n } else {\n logger.error(`Failed to publish message. Status code: ${response.status}`);\n logger.error(`Response: ${await response.text()}`);\n }\n } catch (error) {\n logger.error('Error sending request:', error instanceof Error ? error.message : String(error));\n throw error;\n }\n}\n\nexport { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };\n","import { env } from 'node:process';\nimport { setImmediate } from 'node:timers/promises';\nimport { EventEmitter, once } from 'node:events';\nimport moment from 'moment';\nimport RedisLock from 'redis-lock';\nimport {\n type AmqpConnectionManager, type ChannelWrapper, connect, type CreateChannelOpts,\n} from 'amqp-connection-manager';\n// eslint-disable-next-line import/no-unresolved\nimport type { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser, newTrace, traceTypes, createOrSetRabbitTrace, outbreak,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\n// TODO: [QUORUM-PHASE-3] Delete these env vars\nconst {\n DISABLE_QUORUM_QUEUES_CONSUME,\n DISABLE_QUORUM_QUEUES_PUBLISH,\n} = env;\n\nexport interface IAfRabbitMq {\n ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;\n nack(\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: () => Promise<void>,\n ): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void> ;\n assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;\n assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\ntype newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n};\n\ntype assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ntype AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HEARTBEAT = '60';\n\nclass RabbitMq implements IAfRabbitMq {\n static parseMsg(msg: ConsumeMessage): Message {\n let content = msg.content.toString();\n\n try {\n content = JSON.parse(content);\n } catch { /* ignore error */ }\n\n return {\n ...msg,\n content,\n };\n }\n\n static validateName(type: string, name: string): void {\n if (!name || name === '') {\n throw new RabbitError(`error while using ${type} with no name`);\n }\n }\n\n static getPublishOptions(customHeaders: CustomMessageHeaders = {}): PublishOptions {\n const user = getUser();\n const traceId = outbreak.getCurrentContextTraceId();\n return {\n timestamp: moment().unix(),\n timeout: PUBLISH_TIMEOUT,\n headers: {\n creationTimestamp: moment().valueOf(),\n ...customHeaders,\n [USER_TRACING_HEADER]: user?.id,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n publishChannel: ChannelWrapper | null = null;\n\n publishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly publishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'publishConnectionCreated',\n connectionFailedEventName: 'publishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly em: EventEmitter = new EventEmitter();\n\n readonly exchanges: ExchangesCache = {};\n\n readonly queues: QueuesCache = {};\n\n readonly queueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly assertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n /** A map of consumers' tags used for canceling consumption */\n readonly consumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly consumersToRegister: Array<AfConsumer> = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n // TODO:[QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers\n oldPublishChannel: ChannelWrapper | null = null;\n\n oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly oldPublishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldPublishConnectionCreated',\n connectionFailedEventName: 'oldPublishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldEm: EventEmitter = new EventEmitter();\n\n readonly oldExchanges: ExchangesCache = {};\n\n readonly oldQueues: QueuesCache = {};\n\n readonly oldQueueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly oldAssertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly oldConsumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly oldConsumersToRegister: Array<AfConsumer> = [];\n\n #logger: LoggerInstanceManager;\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger || fallbackLogger;\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.consumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.consumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.em.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async assertChannel({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n if (this.publishChannel && !force) {\n resolve(this.publishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannel({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.publishConnection === connection) {\n this.publishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n async assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n\n if (this.exchanges[exchangeName]) {\n delete this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n if (this.assertExchangePromises[exchangeName]) {\n return this.assertExchangePromises[exchangeName]!;\n }\n\n this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const { publishChannel: channel } = this;\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n this.#logger.debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });\n return channel?.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async bindQueue(queue: string, exchange: string): Promise<void> {\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));\n return channel.bindQueue(queue, exchange, '');\n }\n\n async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.publishConnection;\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': 'quorum',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup(async (setupChannel: ConfirmChannel) => {\n await setupChannel.assertQueue(queueName, localeOptions);\n });\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannel({ force: true, connection });\n await this.deleteQueue(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.queues[queueName] = queue;\n return queue;\n }\n\n // TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues\n static shouldUseQuorum(queueName: string): boolean {\n const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;\n\n if (envQuorumQueuesWhitelist === '*') {\n return true;\n }\n\n if (envQuorumQueuesWhitelist) {\n const whitelist = envQuorumQueuesWhitelist.split(',');\n return whitelist.includes(queueName);\n }\n\n return false;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.queues[queueName]) {\n delete this.queueSetupPromises[queueName];\n return this.queues[queueName]!;\n }\n\n this.queueSetupPromises[queueName] ||= this.setupQueue(queueName, options);\n return this.queueSetupPromises[queueName]!;\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.consumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.consumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n // Used by the microservices to consume messages from the queue\n async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n this.saveConsumerOld(queue, callback, options);\n\n // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n await this.consumeNew(queue, callback, options);\n }\n await this.consumeOld(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore\n async consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbit(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore\n async consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbitOld(queue, callback, options);\n }\n\n private async lockRedisIfNeeded(msg: ReturnType<typeof RabbitMq.parseMsg>, options: ConsumeOptions): Promise<(() => Promise<void>) | null> {\n const { properties: { headers } } = msg;\n const timestamp = headers?.creationTimestamp;\n let releaseLock: (() => Promise<void>) | null = null;\n\n if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {\n releaseLock = await this.redisLock(\n headers.redisTimestampValidationKey,\n options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,\n );\n }\n return releaseLock;\n }\n\n private async unlockRedisIfNeeded(releaseLock?: (() => Promise<void>) | null): Promise<void> {\n if (this.redisLock && releaseLock) {\n await releaseLock();\n }\n }\n\n private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannel({ connection: this.consumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array.`);\n this.consumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // Used by the microservices to consume messages from the exchange\n async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n await this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: this.consumeConnection,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.exchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeNew(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n await this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-exchange-${exchange}-queue-${queue}-old`,\n connection: this.oldConsumeConnection,\n });\n await channelOld.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.oldExchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeOld(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n\n // Used by the microservices to publish messages to the exchange\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], isQuorumQueue = true): Promise<void> {\n await setImmediate();\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n await this.assertVHost();\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await this.assertExchange(exchange, this.publishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n return;\n }\n\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await this.assertExchangeOld(exchange, this.oldPublishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n }\n\n // Used by the microservices to send messages to the queue\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n isQuorumQueue = true,\n ): Promise<boolean | undefined> {\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n try {\n await this.assertVHost();\n await this.assertChannel({ connection: this.publishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueue(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnected();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n } else {\n try {\n await this.assertChannelOld({ connection: this.oldPublishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueueOld(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnectedOld();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n }\n }\n\n async isConnected(): Promise<boolean> {\n let isConnected = true;\n // TODO:[QUORUM-PHASE-3] Remove the condition\n if (!this.gracefulShutdownStarted) {\n if (DISABLE_QUORUM_QUEUES_CONSUME !== 'true' || DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n this.#logger.debug('rabbit: start is connected');\n const [consumeConnection, publishConnection] = await Promise.all([\n this.getConnection(this.consumeConnection),\n this.getConnection(this.publishConnection),\n ]);\n isConnected = consumeConnection.isConnected() && publishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected - false');\n return false;\n }\n try {\n const unRegisteredConsumers = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers');\n }\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.waitForConnect();\n\n await Promise.all(\n this.consumersToRegister.map((c) => channel.checkQueue(c.queue)),\n );\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false', { msg: e.message });\n return false;\n }\n }\n // TODO:[QUORUM-PHASE-3] Delete the old is connected and adjust the return value to return true\n isConnected = await this.isConnectedOld();\n }\n\n this.#logger.debug(`rabbit: isConnected - ${isConnected}`);\n return isConnected;\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.gracefulShutdownStarted = true;\n const tagsNumber = this.consumersTags.size + this.oldConsumersTags.size;\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);\n const cancelTagPromises = [...this.consumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n const cancelTagPromisesOld = [...this.oldConsumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n // Clean the array to avoid race\n this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n const rejected = results.filter((p) => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected}`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');\n }\n }\n\n private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueueOld(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue} old`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array old`);\n this.oldConsumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // TODO: [QUORUM-PHASE-3] Delete all the function under this line.\n async getNewChannelOld({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnectionOld(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n\n if (!localConnection) {\n throw new Error(`rabbit: couldnt get connection for new channel ${name}`);\n }\n\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.oldEm, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n\n return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = await connect(defaultUrls, { findServers });\n\n connection.amqpConnection = newConnection;\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.oldConsumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.oldConsumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.oldEm.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n private saveConsumerOld(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.oldConsumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.oldConsumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n async assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.oldQueues[queueName]) {\n delete this.oldQueueSetupPromises[queueName];\n return this.oldQueues[queueName]!;\n }\n\n this.oldQueueSetupPromises[queueName] ||= this.setupQueueOld(queueName, options);\n return this.oldQueueSetupPromises[queueName]!;\n }\n\n async setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.oldPublishConnection;\n const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannelOld({ force: true, connection });\n await this.deleteQueueOld(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.oldQueues[queueName] = queue;\n return queue;\n }\n\n async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n if (this.oldPublishChannel && !force) {\n resolve(this.oldPublishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannelOld({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.oldPublishConnection === connection) {\n this.oldPublishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n private async deleteQueueOld(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n\n if (this.oldExchanges[exchangeName]) {\n delete this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n if (this.oldAssertExchangePromises[exchangeName]) {\n return this.oldAssertExchangePromises[exchangeName]!;\n }\n\n this.oldAssertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n async isConnectedOld(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return true;\n }\n this.#logger.debug('rabbit: start is connected old');\n const [oldConsumeConnection, oldPublishConnection] = await Promise.all([\n this.getConnectionOld(this.oldConsumeConnection),\n this.getConnectionOld(this.oldPublishConnection),\n ]);\n const isConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected old - false');\n return false;\n }\n\n try {\n const unRegisteredConsumersOld = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumersOld.length > 0) {\n const queueNames = unRegisteredConsumersOld.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues old', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers old');\n }\n\n const channelOld = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await channelOld.waitForConnect();\n\n await Promise.all(\n this.oldConsumersToRegister.map((c) => channelOld.checkQueue(c.queue)),\n );\n return true;\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false old', { msg: e.message });\n return false;\n }\n }\n\n private maskURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n urlObj.username = '***';\n urlObj.password = '***';\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n}\n\nexport default RabbitMq;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["logger: LoggerInstanceManager","message: string","config: RedisConfig","config","DEFAULT_DEAD_TTL_TWO_DAYS: number","DEFAULT_LOCK_TIMEOUT: number","DEFAULT_OPTIONS: ConsumeOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions","c: ChannelWrapper | ConfirmChannel","exchangeName: string","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","data: TaskData","message: TaskMessage","payload: PublishPayload","result: PublishResponse","logger","env","msg: ConsumeMessage","type: string","name: string","customHeaders: CustomMessageHeaders","outbreak","CONTEXTS_IDS_HEADER","EventEmitter","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","fallbackLogger","getRedisInstance","key: string","msg: ConsumeMessageOrNull","channel: ConfirmChannel","releaseLock: (() => Promise<void>) | null","userMsg: ConsumeMessage","queue: string","options: ConsumeOptions","deadQueueOptions: Options.AssertQueue","releaseLock?: (() => Promise<void>) | null","userMsg: ConsumeMessageOrNull","connection: ConnectionData","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","exchangeName: string","channel: ChannelWrapper","exchange: string","setupChannel: ConfirmChannel","queueName: string","options?: Options.AssertQueue","queue: Replies.AssertQueue","callback: CallbackFunction","options: ConsumeOptions | undefined","isConsumerExist: boolean","options?: ConsumeOptions","msg: ReturnType<typeof RabbitMq.parseMsg>","confirmChannel: ConfirmChannel","traceTypes","_: ConsumeMessageOrNull","nackOptions: NackOptions","c: ConfirmChannel","channelOld: ChannelWrapper","content: any","customHeaders?: PublishOptions['headers']","channel","e: RabbitError | any","signal: string","url: string"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.ts","../src/lib/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport type RedisConfig = {\n host: string;\n port: number | undefined;\n prefix?: string;\n}\n\nconst getRedisInstance = (config: RedisConfig): ReturnType<typeof createClient> => createClient({ socket: config });\n\nexport default getRedisInstance;\n","import type { BackoffOptions } from 'exponential-backoff';\nimport type { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport interface ExchangesCache {\n [key: string]: Replies.AssertExchange | undefined;\n}\n\nexport interface QueuesCache {\n [key: string]: Replies.AssertQueue | undefined;\n}\n\nexport interface QueueSetupPromisesDictionary {\n [key: string]: Promise<Replies.AssertQueue> | undefined;\n}\n\nexport interface AssertExchangePromisesDictionary {\n [key: string]: Promise<Replies.AssertExchange> | undefined;\n}\n\nexport type CustomMessageHeaders = {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n // TODO: [QUORUM-PHASE-3] Redundant because all the queues are quorum queues\n isQuorumQueue?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport type newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport type assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n}\nexport type AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport type ConnectionData = {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n};\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\ninterface TaskData {\n [key: string]: any;\n}\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n // eslint-disable-next-line camelcase\n delivery_mode: number;\n // eslint-disable-next-line camelcase\n content_type: string;\n };\n // eslint-disable-next-line camelcase\n routing_key: string;\n payload: string;\n // eslint-disable-next-line camelcase\n payload_encoding: string;\n}\n\ninterface PublishResponse {\n routed: boolean;\n}\n\ninterface SendTaskOptions {\n taskName: string;\n queueName: string;\n}\n\nasync function sendCeleryTaskViaHttp(\n data: TaskData,\n { taskName, queueName }: SendTaskOptions,\n): Promise<void> {\n const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;\n\n const message: TaskMessage = {\n task: taskName,\n id: randomUUID(),\n args: [data],\n };\n\n const payload: PublishPayload = {\n properties: {\n delivery_mode: 2,\n content_type: 'application/json',\n },\n routing_key: queueName,\n payload: JSON.stringify(message),\n payload_encoding: 'string',\n };\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,\n },\n body: JSON.stringify(payload),\n });\n\n if (response.ok) {\n const result: PublishResponse = await response.json();\n logger.info('Successfully published message:', result);\n } else {\n logger.error(`Failed to publish message. Status code: ${response.status}`);\n logger.error(`Response: ${await response.text()}`);\n }\n } catch (error) {\n logger.error('Error sending request:', error instanceof Error ? error.message : String(error));\n throw error;\n }\n}\n\nexport { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };\n","import { env } from 'node:process';\nimport { setImmediate } from 'node:timers/promises';\nimport { EventEmitter, once } from 'node:events';\nimport moment from 'moment';\nimport RedisLock from 'redis-lock';\nimport {\n type AmqpConnectionManager, type ChannelWrapper, connect, type CreateChannelOpts,\n} from 'amqp-connection-manager';\n// eslint-disable-next-line import/no-unresolved\nimport type { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\n// TODO: [QUORUM-PHASE-3] Delete these env vars\nconst {\n DISABLE_QUORUM_QUEUES_CONSUME,\n DISABLE_QUORUM_QUEUES_PUBLISH,\n} = env;\n\nexport interface IAfRabbitMq {\n ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;\n nack(\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: () => Promise<void>,\n ): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void> ;\n assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;\n assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\ntype newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n};\n\ntype assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ntype AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HEARTBEAT = '60';\n\nclass RabbitMq implements IAfRabbitMq {\n static parseMsg(msg: ConsumeMessage): Message {\n let content = msg.content.toString();\n\n try {\n content = JSON.parse(content);\n } catch { /* ignore error */ }\n\n return {\n ...msg,\n content,\n };\n }\n\n static validateName(type: string, name: string): void {\n if (!name || name === '') {\n throw new RabbitError(`error while using ${type} with no name`);\n }\n }\n\n static getPublishOptions(customHeaders: CustomMessageHeaders = {}): PublishOptions {\n const user = getUser();\n const traceId = outbreak.getCurrentContextTraceId();\n return {\n timestamp: moment().unix(),\n timeout: PUBLISH_TIMEOUT,\n headers: {\n creationTimestamp: moment().valueOf(),\n ...customHeaders,\n [USER_TRACING_HEADER]: user?.id,\n [CONTEXTS_IDS_HEADER]: user?.contextIds,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n publishChannel: ChannelWrapper | null = null;\n\n publishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly publishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'publishConnectionCreated',\n connectionFailedEventName: 'publishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly em: EventEmitter = new EventEmitter();\n\n readonly exchanges: ExchangesCache = {};\n\n readonly queues: QueuesCache = {};\n\n readonly queueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly assertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n /** A map of consumers' tags used for canceling consumption */\n readonly consumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly consumersToRegister: Array<AfConsumer> = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n // TODO:[QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers\n oldPublishChannel: ChannelWrapper | null = null;\n\n oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly oldPublishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldPublishConnectionCreated',\n connectionFailedEventName: 'oldPublishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldEm: EventEmitter = new EventEmitter();\n\n readonly oldExchanges: ExchangesCache = {};\n\n readonly oldQueues: QueuesCache = {};\n\n readonly oldQueueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly oldAssertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly oldConsumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly oldConsumersToRegister: Array<AfConsumer> = [];\n\n #logger: LoggerInstanceManager;\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger || fallbackLogger;\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.consumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.consumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.em.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async assertChannel({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n if (this.publishChannel && !force) {\n resolve(this.publishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannel({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.publishConnection === connection) {\n this.publishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n async assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n\n if (this.exchanges[exchangeName]) {\n delete this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n if (this.assertExchangePromises[exchangeName]) {\n return this.assertExchangePromises[exchangeName]!;\n }\n\n this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const { publishChannel: channel } = this;\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n this.#logger.debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });\n return channel?.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async bindQueue(queue: string, exchange: string): Promise<void> {\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));\n return channel.bindQueue(queue, exchange, '');\n }\n\n async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.publishConnection;\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': 'quorum',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup(async (setupChannel: ConfirmChannel) => {\n await setupChannel.assertQueue(queueName, localeOptions);\n });\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannel({ force: true, connection });\n await this.deleteQueue(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.queues[queueName] = queue;\n return queue;\n }\n\n // TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues\n static shouldUseQuorum(queueName: string): boolean {\n const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;\n\n if (envQuorumQueuesWhitelist === '*') {\n return true;\n }\n\n if (envQuorumQueuesWhitelist) {\n const whitelist = envQuorumQueuesWhitelist.split(',');\n return whitelist.includes(queueName);\n }\n\n return false;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.queues[queueName]) {\n delete this.queueSetupPromises[queueName];\n return this.queues[queueName]!;\n }\n\n this.queueSetupPromises[queueName] ||= this.setupQueue(queueName, options);\n return this.queueSetupPromises[queueName]!;\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.consumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.consumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n // Used by the microservices to consume messages from the queue\n async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n this.saveConsumerOld(queue, callback, options);\n\n // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n await this.consumeNew(queue, callback, options);\n }\n await this.consumeOld(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore\n async consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbit(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore\n async consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbitOld(queue, callback, options);\n }\n\n private async lockRedisIfNeeded(msg: ReturnType<typeof RabbitMq.parseMsg>, options: ConsumeOptions): Promise<(() => Promise<void>) | null> {\n const { properties: { headers } } = msg;\n const timestamp = headers?.creationTimestamp;\n let releaseLock: (() => Promise<void>) | null = null;\n\n if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {\n releaseLock = await this.redisLock(\n headers.redisTimestampValidationKey,\n options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,\n );\n }\n return releaseLock;\n }\n\n private async unlockRedisIfNeeded(releaseLock?: (() => Promise<void>) | null): Promise<void> {\n if (this.redisLock && releaseLock) {\n await releaseLock();\n }\n }\n\n private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannel({ connection: this.consumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers || {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array.`);\n this.consumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // Used by the microservices to consume messages from the exchange\n async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n await this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: this.consumeConnection,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.exchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeNew(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n await this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-exchange-${exchange}-queue-${queue}-old`,\n connection: this.oldConsumeConnection,\n });\n await channelOld.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.oldExchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeOld(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n\n // Used by the microservices to publish messages to the exchange\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], isQuorumQueue = true): Promise<void> {\n await setImmediate();\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n await this.assertVHost();\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await this.assertExchange(exchange, this.publishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n return;\n }\n\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await this.assertExchangeOld(exchange, this.oldPublishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n }\n\n // Used by the microservices to send messages to the queue\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n isQuorumQueue = true,\n ): Promise<boolean | undefined> {\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n try {\n await this.assertVHost();\n await this.assertChannel({ connection: this.publishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueue(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnected();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n } else {\n try {\n await this.assertChannelOld({ connection: this.oldPublishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueueOld(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnectedOld();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n }\n }\n\n async isConnected(): Promise<boolean> {\n let isConnected = true;\n // TODO:[QUORUM-PHASE-3] Remove the condition\n if (!this.gracefulShutdownStarted) {\n if (DISABLE_QUORUM_QUEUES_CONSUME !== 'true' || DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n this.#logger.debug('rabbit: start is connected');\n const [consumeConnection, publishConnection] = await Promise.all([\n this.getConnection(this.consumeConnection),\n this.getConnection(this.publishConnection),\n ]);\n isConnected = consumeConnection.isConnected() && publishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected - false');\n return false;\n }\n try {\n const unRegisteredConsumers = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers');\n }\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.waitForConnect();\n\n await Promise.all(\n this.consumersToRegister.map((c) => channel.checkQueue(c.queue)),\n );\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false', { msg: e.message });\n return false;\n }\n }\n // TODO:[QUORUM-PHASE-3] Delete the old is connected and adjust the return value to return true\n isConnected = await this.isConnectedOld();\n }\n\n this.#logger.debug(`rabbit: isConnected - ${isConnected}`);\n return isConnected;\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.gracefulShutdownStarted = true;\n const tagsNumber = this.consumersTags.size + this.oldConsumersTags.size;\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);\n const cancelTagPromises = [...this.consumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n const cancelTagPromisesOld = [...this.oldConsumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n // Clean the array to avoid race\n this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n const rejected = results.filter((p) => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected}`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');\n }\n }\n\n private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueueOld(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers || {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue} old`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array old`);\n this.oldConsumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // TODO: [QUORUM-PHASE-3] Delete all the function under this line.\n async getNewChannelOld({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnectionOld(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n\n if (!localConnection) {\n throw new Error(`rabbit: couldnt get connection for new channel ${name}`);\n }\n\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.oldEm, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n\n return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = await connect(defaultUrls, { findServers });\n\n connection.amqpConnection = newConnection;\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.oldConsumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.oldConsumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.oldEm.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n private saveConsumerOld(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.oldConsumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.oldConsumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n async assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.oldQueues[queueName]) {\n delete this.oldQueueSetupPromises[queueName];\n return this.oldQueues[queueName]!;\n }\n\n this.oldQueueSetupPromises[queueName] ||= this.setupQueueOld(queueName, options);\n return this.oldQueueSetupPromises[queueName]!;\n }\n\n async setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.oldPublishConnection;\n const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannelOld({ force: true, connection });\n await this.deleteQueueOld(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.oldQueues[queueName] = queue;\n return queue;\n }\n\n async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n if (this.oldPublishChannel && !force) {\n resolve(this.oldPublishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannelOld({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.oldPublishConnection === connection) {\n this.oldPublishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n private async deleteQueueOld(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n\n if (this.oldExchanges[exchangeName]) {\n delete this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n if (this.oldAssertExchangePromises[exchangeName]) {\n return this.oldAssertExchangePromises[exchangeName]!;\n }\n\n this.oldAssertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n async isConnectedOld(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return true;\n }\n this.#logger.debug('rabbit: start is connected old');\n const [oldConsumeConnection, oldPublishConnection] = await Promise.all([\n this.getConnectionOld(this.oldConsumeConnection),\n this.getConnectionOld(this.oldPublishConnection),\n ]);\n const isConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected old - false');\n return false;\n }\n\n try {\n const unRegisteredConsumersOld = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumersOld.length > 0) {\n const queueNames = unRegisteredConsumersOld.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues old', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers old');\n }\n\n const channelOld = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await channelOld.waitForConnect();\n\n await Promise.all(\n this.oldConsumersToRegister.map((c) => channelOld.checkQueue(c.queue)),\n );\n return true;\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false old', { msg: e.message });\n return false;\n }\n }\n\n private maskURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n urlObj.username = '***';\n urlObj.password = '***';\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n}\n\nexport default RabbitMq;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import moment from "moment";
5
5
  import RedisLock from "redis-lock";
6
6
  import { connect } from "amqp-connection-manager";
7
7
  import { backOff } from "exponential-backoff";
8
- import { createOrSetRabbitTrace, getUser, newTrace, outbreak, traceTypes } from "@autofleet/zehut";
8
+ import { CONTEXTS_IDS_HEADER, createOrSetRabbitTrace, getUser, newTrace, outbreak, traceTypes } from "@autofleet/zehut";
9
9
  import { randomUUID } from "node:crypto";
10
10
  import Logger from "@autofleet/logger";
11
11
  import { createClient } from "redis";
@@ -163,6 +163,7 @@ var RabbitMq = class RabbitMq {
163
163
  creationTimestamp: moment().valueOf(),
164
164
  ...customHeaders,
165
165
  [USER_TRACING_HEADER]: user?.id,
166
+ [CONTEXTS_IDS_HEADER]: user?.contextIds,
166
167
  [TRACING_HEADER]: traceId
167
168
  }
168
169
  };
@@ -600,12 +601,12 @@ var RabbitMq = class RabbitMq {
600
601
  await confirmChannel.prefetch(limit, false);
601
602
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
602
603
  if (!msg) return null;
603
- const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};
604
+ const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds } = msg.properties.headers || {};
604
605
  const parsedMessage = RabbitMq.parseMsg(msg);
605
606
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
606
607
  const trace = newTrace(traceTypes.RABBIT);
607
608
  if (userId && enableRabbitTrace) try {
608
- await createOrSetRabbitTrace(trace, userId);
609
+ await createOrSetRabbitTrace(trace, userId, userContextIds);
609
610
  } catch (e) {
610
611
  this.#logger.error("rabbit: failed to setRabbitTrace", {
611
612
  userId,
@@ -822,12 +823,12 @@ var RabbitMq = class RabbitMq {
822
823
  await confirmChannel.prefetch(limit, false);
823
824
  const { consumerTag } = await confirmChannel.consume(queue, async (msg) => {
824
825
  if (!msg) return null;
825
- const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};
826
+ const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds } = msg.properties.headers || {};
826
827
  const parsedMessage = RabbitMq.parseMsg(msg);
827
828
  const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);
828
829
  const trace = newTrace(traceTypes.RABBIT);
829
830
  if (userId && enableRabbitTrace) try {
830
- await createOrSetRabbitTrace(trace, userId);
831
+ await createOrSetRabbitTrace(trace, userId, userContextIds);
831
832
  } catch (e) {
832
833
  this.#logger.error("rabbit: failed to setRabbitTrace", {
833
834
  userId,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["logger: LoggerInstanceManager","message: string","config: RedisConfig","config","DEFAULT_DEAD_TTL_TWO_DAYS: number","DEFAULT_LOCK_TIMEOUT: number","DEFAULT_OPTIONS: ConsumeOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions","c: ChannelWrapper | ConfirmChannel","exchangeName: string","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","data: TaskData","message: TaskMessage","payload: PublishPayload","result: PublishResponse","logger","msg: ConsumeMessage","type: string","name: string","customHeaders: CustomMessageHeaders","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","fallbackLogger","getRedisInstance","key: string","msg: ConsumeMessageOrNull","channel: ConfirmChannel","releaseLock: (() => Promise<void>) | null","userMsg: ConsumeMessage","queue: string","options: ConsumeOptions","deadQueueOptions: Options.AssertQueue","releaseLock?: (() => Promise<void>) | null","userMsg: ConsumeMessageOrNull","connection: ConnectionData","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","exchangeName: string","channel: ChannelWrapper","exchange: string","setupChannel: ConfirmChannel","queueName: string","options?: Options.AssertQueue","queue: Replies.AssertQueue","callback: CallbackFunction","options: ConsumeOptions | undefined","isConsumerExist: boolean","options?: ConsumeOptions","msg: ReturnType<typeof RabbitMq.parseMsg>","confirmChannel: ConfirmChannel","_: ConsumeMessageOrNull","nackOptions: NackOptions","c: ConfirmChannel","channelOld: ChannelWrapper","content: any","customHeaders?: PublishOptions['headers']","channel","e: RabbitError | any","signal: string","url: string"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.ts","../src/lib/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport type RedisConfig = {\n host: string;\n port: number | undefined;\n prefix?: string;\n}\n\nconst getRedisInstance = (config: RedisConfig): ReturnType<typeof createClient> => createClient({ socket: config });\n\nexport default getRedisInstance;\n","import type { BackoffOptions } from 'exponential-backoff';\nimport type { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport interface ExchangesCache {\n [key: string]: Replies.AssertExchange | undefined;\n}\n\nexport interface QueuesCache {\n [key: string]: Replies.AssertQueue | undefined;\n}\n\nexport interface QueueSetupPromisesDictionary {\n [key: string]: Promise<Replies.AssertQueue> | undefined;\n}\n\nexport interface AssertExchangePromisesDictionary {\n [key: string]: Promise<Replies.AssertExchange> | undefined;\n}\n\nexport type CustomMessageHeaders = {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n // TODO: [QUORUM-PHASE-3] Redundant because all the queues are quorum queues\n isQuorumQueue?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport type newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport type assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n}\nexport type AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport type ConnectionData = {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n};\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\ninterface TaskData {\n [key: string]: any;\n}\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n // eslint-disable-next-line camelcase\n delivery_mode: number;\n // eslint-disable-next-line camelcase\n content_type: string;\n };\n // eslint-disable-next-line camelcase\n routing_key: string;\n payload: string;\n // eslint-disable-next-line camelcase\n payload_encoding: string;\n}\n\ninterface PublishResponse {\n routed: boolean;\n}\n\ninterface SendTaskOptions {\n taskName: string;\n queueName: string;\n}\n\nasync function sendCeleryTaskViaHttp(\n data: TaskData,\n { taskName, queueName }: SendTaskOptions,\n): Promise<void> {\n const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;\n\n const message: TaskMessage = {\n task: taskName,\n id: randomUUID(),\n args: [data],\n };\n\n const payload: PublishPayload = {\n properties: {\n delivery_mode: 2,\n content_type: 'application/json',\n },\n routing_key: queueName,\n payload: JSON.stringify(message),\n payload_encoding: 'string',\n };\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,\n },\n body: JSON.stringify(payload),\n });\n\n if (response.ok) {\n const result: PublishResponse = await response.json();\n logger.info('Successfully published message:', result);\n } else {\n logger.error(`Failed to publish message. Status code: ${response.status}`);\n logger.error(`Response: ${await response.text()}`);\n }\n } catch (error) {\n logger.error('Error sending request:', error instanceof Error ? error.message : String(error));\n throw error;\n }\n}\n\nexport { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };\n","import { env } from 'node:process';\nimport { setImmediate } from 'node:timers/promises';\nimport { EventEmitter, once } from 'node:events';\nimport moment from 'moment';\nimport RedisLock from 'redis-lock';\nimport {\n type AmqpConnectionManager, type ChannelWrapper, connect, type CreateChannelOpts,\n} from 'amqp-connection-manager';\n// eslint-disable-next-line import/no-unresolved\nimport type { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser, newTrace, traceTypes, createOrSetRabbitTrace, outbreak,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\n// TODO: [QUORUM-PHASE-3] Delete these env vars\nconst {\n DISABLE_QUORUM_QUEUES_CONSUME,\n DISABLE_QUORUM_QUEUES_PUBLISH,\n} = env;\n\nexport interface IAfRabbitMq {\n ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;\n nack(\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: () => Promise<void>,\n ): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void> ;\n assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;\n assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\ntype newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n};\n\ntype assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ntype AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HEARTBEAT = '60';\n\nclass RabbitMq implements IAfRabbitMq {\n static parseMsg(msg: ConsumeMessage): Message {\n let content = msg.content.toString();\n\n try {\n content = JSON.parse(content);\n } catch { /* ignore error */ }\n\n return {\n ...msg,\n content,\n };\n }\n\n static validateName(type: string, name: string): void {\n if (!name || name === '') {\n throw new RabbitError(`error while using ${type} with no name`);\n }\n }\n\n static getPublishOptions(customHeaders: CustomMessageHeaders = {}): PublishOptions {\n const user = getUser();\n const traceId = outbreak.getCurrentContextTraceId();\n return {\n timestamp: moment().unix(),\n timeout: PUBLISH_TIMEOUT,\n headers: {\n creationTimestamp: moment().valueOf(),\n ...customHeaders,\n [USER_TRACING_HEADER]: user?.id,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n publishChannel: ChannelWrapper | null = null;\n\n publishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly publishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'publishConnectionCreated',\n connectionFailedEventName: 'publishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly em: EventEmitter = new EventEmitter();\n\n readonly exchanges: ExchangesCache = {};\n\n readonly queues: QueuesCache = {};\n\n readonly queueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly assertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n /** A map of consumers' tags used for canceling consumption */\n readonly consumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly consumersToRegister: Array<AfConsumer> = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n // TODO:[QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers\n oldPublishChannel: ChannelWrapper | null = null;\n\n oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly oldPublishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldPublishConnectionCreated',\n connectionFailedEventName: 'oldPublishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldEm: EventEmitter = new EventEmitter();\n\n readonly oldExchanges: ExchangesCache = {};\n\n readonly oldQueues: QueuesCache = {};\n\n readonly oldQueueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly oldAssertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly oldConsumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly oldConsumersToRegister: Array<AfConsumer> = [];\n\n #logger: LoggerInstanceManager;\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger || fallbackLogger;\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.consumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.consumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.em.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async assertChannel({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n if (this.publishChannel && !force) {\n resolve(this.publishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannel({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.publishConnection === connection) {\n this.publishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n async assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n\n if (this.exchanges[exchangeName]) {\n delete this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n if (this.assertExchangePromises[exchangeName]) {\n return this.assertExchangePromises[exchangeName]!;\n }\n\n this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const { publishChannel: channel } = this;\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n this.#logger.debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });\n return channel?.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async bindQueue(queue: string, exchange: string): Promise<void> {\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));\n return channel.bindQueue(queue, exchange, '');\n }\n\n async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.publishConnection;\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': 'quorum',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup(async (setupChannel: ConfirmChannel) => {\n await setupChannel.assertQueue(queueName, localeOptions);\n });\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannel({ force: true, connection });\n await this.deleteQueue(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.queues[queueName] = queue;\n return queue;\n }\n\n // TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues\n static shouldUseQuorum(queueName: string): boolean {\n const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;\n\n if (envQuorumQueuesWhitelist === '*') {\n return true;\n }\n\n if (envQuorumQueuesWhitelist) {\n const whitelist = envQuorumQueuesWhitelist.split(',');\n return whitelist.includes(queueName);\n }\n\n return false;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.queues[queueName]) {\n delete this.queueSetupPromises[queueName];\n return this.queues[queueName]!;\n }\n\n this.queueSetupPromises[queueName] ||= this.setupQueue(queueName, options);\n return this.queueSetupPromises[queueName]!;\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.consumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.consumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n // Used by the microservices to consume messages from the queue\n async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n this.saveConsumerOld(queue, callback, options);\n\n // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n await this.consumeNew(queue, callback, options);\n }\n await this.consumeOld(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore\n async consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbit(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore\n async consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbitOld(queue, callback, options);\n }\n\n private async lockRedisIfNeeded(msg: ReturnType<typeof RabbitMq.parseMsg>, options: ConsumeOptions): Promise<(() => Promise<void>) | null> {\n const { properties: { headers } } = msg;\n const timestamp = headers?.creationTimestamp;\n let releaseLock: (() => Promise<void>) | null = null;\n\n if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {\n releaseLock = await this.redisLock(\n headers.redisTimestampValidationKey,\n options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,\n );\n }\n return releaseLock;\n }\n\n private async unlockRedisIfNeeded(releaseLock?: (() => Promise<void>) | null): Promise<void> {\n if (this.redisLock && releaseLock) {\n await releaseLock();\n }\n }\n\n private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannel({ connection: this.consumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array.`);\n this.consumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // Used by the microservices to consume messages from the exchange\n async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n await this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: this.consumeConnection,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.exchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeNew(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n await this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-exchange-${exchange}-queue-${queue}-old`,\n connection: this.oldConsumeConnection,\n });\n await channelOld.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.oldExchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeOld(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n\n // Used by the microservices to publish messages to the exchange\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], isQuorumQueue = true): Promise<void> {\n await setImmediate();\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n await this.assertVHost();\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await this.assertExchange(exchange, this.publishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n return;\n }\n\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await this.assertExchangeOld(exchange, this.oldPublishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n }\n\n // Used by the microservices to send messages to the queue\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n isQuorumQueue = true,\n ): Promise<boolean | undefined> {\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n try {\n await this.assertVHost();\n await this.assertChannel({ connection: this.publishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueue(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnected();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n } else {\n try {\n await this.assertChannelOld({ connection: this.oldPublishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueueOld(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnectedOld();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n }\n }\n\n async isConnected(): Promise<boolean> {\n let isConnected = true;\n // TODO:[QUORUM-PHASE-3] Remove the condition\n if (!this.gracefulShutdownStarted) {\n if (DISABLE_QUORUM_QUEUES_CONSUME !== 'true' || DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n this.#logger.debug('rabbit: start is connected');\n const [consumeConnection, publishConnection] = await Promise.all([\n this.getConnection(this.consumeConnection),\n this.getConnection(this.publishConnection),\n ]);\n isConnected = consumeConnection.isConnected() && publishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected - false');\n return false;\n }\n try {\n const unRegisteredConsumers = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers');\n }\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.waitForConnect();\n\n await Promise.all(\n this.consumersToRegister.map((c) => channel.checkQueue(c.queue)),\n );\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false', { msg: e.message });\n return false;\n }\n }\n // TODO:[QUORUM-PHASE-3] Delete the old is connected and adjust the return value to return true\n isConnected = await this.isConnectedOld();\n }\n\n this.#logger.debug(`rabbit: isConnected - ${isConnected}`);\n return isConnected;\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.gracefulShutdownStarted = true;\n const tagsNumber = this.consumersTags.size + this.oldConsumersTags.size;\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);\n const cancelTagPromises = [...this.consumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n const cancelTagPromisesOld = [...this.oldConsumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n // Clean the array to avoid race\n this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n const rejected = results.filter((p) => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected}`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');\n }\n }\n\n private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueueOld(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const { [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue} old`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array old`);\n this.oldConsumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // TODO: [QUORUM-PHASE-3] Delete all the function under this line.\n async getNewChannelOld({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnectionOld(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n\n if (!localConnection) {\n throw new Error(`rabbit: couldnt get connection for new channel ${name}`);\n }\n\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.oldEm, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n\n return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = await connect(defaultUrls, { findServers });\n\n connection.amqpConnection = newConnection;\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.oldConsumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.oldConsumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.oldEm.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n private saveConsumerOld(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.oldConsumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.oldConsumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n async assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.oldQueues[queueName]) {\n delete this.oldQueueSetupPromises[queueName];\n return this.oldQueues[queueName]!;\n }\n\n this.oldQueueSetupPromises[queueName] ||= this.setupQueueOld(queueName, options);\n return this.oldQueueSetupPromises[queueName]!;\n }\n\n async setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.oldPublishConnection;\n const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannelOld({ force: true, connection });\n await this.deleteQueueOld(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.oldQueues[queueName] = queue;\n return queue;\n }\n\n async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n if (this.oldPublishChannel && !force) {\n resolve(this.oldPublishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannelOld({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.oldPublishConnection === connection) {\n this.oldPublishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n private async deleteQueueOld(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n\n if (this.oldExchanges[exchangeName]) {\n delete this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n if (this.oldAssertExchangePromises[exchangeName]) {\n return this.oldAssertExchangePromises[exchangeName]!;\n }\n\n this.oldAssertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n async isConnectedOld(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return true;\n }\n this.#logger.debug('rabbit: start is connected old');\n const [oldConsumeConnection, oldPublishConnection] = await Promise.all([\n this.getConnectionOld(this.oldConsumeConnection),\n this.getConnectionOld(this.oldPublishConnection),\n ]);\n const isConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected old - false');\n return false;\n }\n\n try {\n const unRegisteredConsumersOld = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumersOld.length > 0) {\n const queueNames = unRegisteredConsumersOld.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues old', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers old');\n }\n\n const channelOld = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await channelOld.waitForConnect();\n\n await Promise.all(\n this.oldConsumersToRegister.map((c) => channelOld.checkQueue(c.queue)),\n );\n return true;\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false old', { msg: e.message });\n return false;\n }\n }\n\n private maskURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n urlObj.username = '***';\n urlObj.password = '***';\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n}\n\nexport default RabbitMq;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["logger: LoggerInstanceManager","message: string","config: RedisConfig","config","DEFAULT_DEAD_TTL_TWO_DAYS: number","DEFAULT_LOCK_TIMEOUT: number","DEFAULT_OPTIONS: ConsumeOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions","ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions","c: ChannelWrapper | ConfirmChannel","exchangeName: string","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","data: TaskData","message: TaskMessage","payload: PublishPayload","result: PublishResponse","logger","msg: ConsumeMessage","type: string","name: string","customHeaders: CustomMessageHeaders","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","fallbackLogger","getRedisInstance","key: string","msg: ConsumeMessageOrNull","channel: ConfirmChannel","releaseLock: (() => Promise<void>) | null","userMsg: ConsumeMessage","queue: string","options: ConsumeOptions","deadQueueOptions: Options.AssertQueue","releaseLock?: (() => Promise<void>) | null","userMsg: ConsumeMessageOrNull","connection: ConnectionData","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","exchangeName: string","channel: ChannelWrapper","exchange: string","setupChannel: ConfirmChannel","queueName: string","options?: Options.AssertQueue","queue: Replies.AssertQueue","callback: CallbackFunction","options: ConsumeOptions | undefined","isConsumerExist: boolean","options?: ConsumeOptions","msg: ReturnType<typeof RabbitMq.parseMsg>","confirmChannel: ConfirmChannel","_: ConsumeMessageOrNull","nackOptions: NackOptions","c: ConfirmChannel","channelOld: ChannelWrapper","content: any","customHeaders?: PublishOptions['headers']","channel","e: RabbitError | any","signal: string","url: string"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.ts","../src/lib/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport type RedisConfig = {\n host: string;\n port: number | undefined;\n prefix?: string;\n}\n\nconst getRedisInstance = (config: RedisConfig): ReturnType<typeof createClient> => createClient({ socket: config });\n\nexport default getRedisInstance;\n","import type { BackoffOptions } from 'exponential-backoff';\nimport type { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport interface ExchangesCache {\n [key: string]: Replies.AssertExchange | undefined;\n}\n\nexport interface QueuesCache {\n [key: string]: Replies.AssertQueue | undefined;\n}\n\nexport interface QueueSetupPromisesDictionary {\n [key: string]: Promise<Replies.AssertQueue> | undefined;\n}\n\nexport interface AssertExchangePromisesDictionary {\n [key: string]: Promise<Replies.AssertExchange> | undefined;\n}\n\nexport type CustomMessageHeaders = {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n // TODO: [QUORUM-PHASE-3] Redundant because all the queues are quorum queues\n isQuorumQueue?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport type newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport type assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n}\nexport type AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport type ConnectionData = {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n};\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\ninterface TaskData {\n [key: string]: any;\n}\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n // eslint-disable-next-line camelcase\n delivery_mode: number;\n // eslint-disable-next-line camelcase\n content_type: string;\n };\n // eslint-disable-next-line camelcase\n routing_key: string;\n payload: string;\n // eslint-disable-next-line camelcase\n payload_encoding: string;\n}\n\ninterface PublishResponse {\n routed: boolean;\n}\n\ninterface SendTaskOptions {\n taskName: string;\n queueName: string;\n}\n\nasync function sendCeleryTaskViaHttp(\n data: TaskData,\n { taskName, queueName }: SendTaskOptions,\n): Promise<void> {\n const apiUrl = `http://${config.host}:15672/api/exchanges/%2f/amq.default/publish`;\n\n const message: TaskMessage = {\n task: taskName,\n id: randomUUID(),\n args: [data],\n };\n\n const payload: PublishPayload = {\n properties: {\n delivery_mode: 2,\n content_type: 'application/json',\n },\n routing_key: queueName,\n payload: JSON.stringify(message),\n payload_encoding: 'string',\n };\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Basic ${Buffer.from(`${config.username}:${config.password}`).toString('base64')}`,\n },\n body: JSON.stringify(payload),\n });\n\n if (response.ok) {\n const result: PublishResponse = await response.json();\n logger.info('Successfully published message:', result);\n } else {\n logger.error(`Failed to publish message. Status code: ${response.status}`);\n logger.error(`Response: ${await response.text()}`);\n }\n } catch (error) {\n logger.error('Error sending request:', error instanceof Error ? error.message : String(error));\n throw error;\n }\n}\n\nexport { sendCeleryTaskViaHttp, TaskData, SendTaskOptions };\n","import { env } from 'node:process';\nimport { setImmediate } from 'node:timers/promises';\nimport { EventEmitter, once } from 'node:events';\nimport moment from 'moment';\nimport RedisLock from 'redis-lock';\nimport {\n type AmqpConnectionManager, type ChannelWrapper, connect, type CreateChannelOpts,\n} from 'amqp-connection-manager';\n// eslint-disable-next-line import/no-unresolved\nimport type { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\n// TODO: [QUORUM-PHASE-3] Delete these env vars\nconst {\n DISABLE_QUORUM_QUEUES_CONSUME,\n DISABLE_QUORUM_QUEUES_PUBLISH,\n} = env;\n\nexport interface IAfRabbitMq {\n ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;\n nack(\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: () => Promise<void>,\n ): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void> ;\n assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;\n assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\ntype newChannelOpts = {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n};\n\ntype assertChannelOpts = {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ntype AfConsumer = {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HEARTBEAT = '60';\n\nclass RabbitMq implements IAfRabbitMq {\n static parseMsg(msg: ConsumeMessage): Message {\n let content = msg.content.toString();\n\n try {\n content = JSON.parse(content);\n } catch { /* ignore error */ }\n\n return {\n ...msg,\n content,\n };\n }\n\n static validateName(type: string, name: string): void {\n if (!name || name === '') {\n throw new RabbitError(`error while using ${type} with no name`);\n }\n }\n\n static getPublishOptions(customHeaders: CustomMessageHeaders = {}): PublishOptions {\n const user = getUser();\n const traceId = outbreak.getCurrentContextTraceId();\n return {\n timestamp: moment().unix(),\n timeout: PUBLISH_TIMEOUT,\n headers: {\n creationTimestamp: moment().valueOf(),\n ...customHeaders,\n [USER_TRACING_HEADER]: user?.id,\n [CONTEXTS_IDS_HEADER]: user?.contextIds,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n publishChannel: ChannelWrapper | null = null;\n\n publishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly publishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'publishConnectionCreated',\n connectionFailedEventName: 'publishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly em: EventEmitter = new EventEmitter();\n\n readonly exchanges: ExchangesCache = {};\n\n readonly queues: QueuesCache = {};\n\n readonly queueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly assertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n /** A map of consumers' tags used for canceling consumption */\n readonly consumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly consumersToRegister: Array<AfConsumer> = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n // TODO:[QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers\n oldPublishChannel: ChannelWrapper | null = null;\n\n oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly oldPublishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldPublishConnectionCreated',\n connectionFailedEventName: 'oldPublishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldEm: EventEmitter = new EventEmitter();\n\n readonly oldExchanges: ExchangesCache = {};\n\n readonly oldQueues: QueuesCache = {};\n\n readonly oldQueueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly oldAssertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly oldConsumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string }> = new Map<string, { channel: ConfirmChannel; consumerTag: string }>();\n\n private readonly oldConsumersToRegister: Array<AfConsumer> = [];\n\n #logger: LoggerInstanceManager;\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger || fallbackLogger;\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.consumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.consumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.em.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async assertChannel({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n if (this.publishChannel && !force) {\n resolve(this.publishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannel({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.publishConnection === connection) {\n this.publishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n async assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n\n if (this.exchanges[exchangeName]) {\n delete this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n if (this.assertExchangePromises[exchangeName]) {\n return this.assertExchangePromises[exchangeName]!;\n }\n\n this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName]!;\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const { publishChannel: channel } = this;\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n this.#logger.debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });\n return channel?.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async bindQueue(queue: string, exchange: string): Promise<void> {\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));\n return channel.bindQueue(queue, exchange, '');\n }\n\n async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.publishConnection;\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': 'quorum',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup(async (setupChannel: ConfirmChannel) => {\n await setupChannel.assertQueue(queueName, localeOptions);\n });\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannel({ force: true, connection });\n await this.deleteQueue(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.queues[queueName] = queue;\n return queue;\n }\n\n // TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues\n static shouldUseQuorum(queueName: string): boolean {\n const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;\n\n if (envQuorumQueuesWhitelist === '*') {\n return true;\n }\n\n if (envQuorumQueuesWhitelist) {\n const whitelist = envQuorumQueuesWhitelist.split(',');\n return whitelist.includes(queueName);\n }\n\n return false;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.queues[queueName]) {\n delete this.queueSetupPromises[queueName];\n return this.queues[queueName]!;\n }\n\n this.queueSetupPromises[queueName] ||= this.setupQueue(queueName, options);\n return this.queueSetupPromises[queueName]!;\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.consumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.consumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n // Used by the microservices to consume messages from the queue\n async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n this.saveConsumerOld(queue, callback, options);\n\n // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n await this.consumeNew(queue, callback, options);\n }\n await this.consumeOld(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore\n async consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbit(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore\n async consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbitOld(queue, callback, options);\n }\n\n private async lockRedisIfNeeded(msg: ReturnType<typeof RabbitMq.parseMsg>, options: ConsumeOptions): Promise<(() => Promise<void>) | null> {\n const { properties: { headers } } = msg;\n const timestamp = headers?.creationTimestamp;\n let releaseLock: (() => Promise<void>) | null = null;\n\n if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {\n releaseLock = await this.redisLock(\n headers.redisTimestampValidationKey,\n options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,\n );\n }\n return releaseLock;\n }\n\n private async unlockRedisIfNeeded(releaseLock?: (() => Promise<void>) | null): Promise<void> {\n if (this.redisLock && releaseLock) {\n await releaseLock();\n }\n }\n\n private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannel({ connection: this.consumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers || {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array.`);\n this.consumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // Used by the microservices to consume messages from the exchange\n async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions) : Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n await this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: this.consumeConnection,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.exchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeNew(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n await this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-exchange-${exchange}-queue-${queue}-old`,\n connection: this.oldConsumeConnection,\n });\n await channelOld.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.oldExchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeOld(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n\n // Used by the microservices to publish messages to the exchange\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], isQuorumQueue = true): Promise<void> {\n await setImmediate();\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n await this.assertVHost();\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await this.assertExchange(exchange, this.publishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n return;\n }\n\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await this.assertExchangeOld(exchange, this.oldPublishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n }\n\n // Used by the microservices to send messages to the queue\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n isQuorumQueue = true,\n ): Promise<boolean | undefined> {\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n try {\n await this.assertVHost();\n await this.assertChannel({ connection: this.publishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueue(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnected();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n } else {\n try {\n await this.assertChannelOld({ connection: this.oldPublishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueueOld(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnectedOld();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n }\n }\n\n async isConnected(): Promise<boolean> {\n let isConnected = true;\n // TODO:[QUORUM-PHASE-3] Remove the condition\n if (!this.gracefulShutdownStarted) {\n if (DISABLE_QUORUM_QUEUES_CONSUME !== 'true' || DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n this.#logger.debug('rabbit: start is connected');\n const [consumeConnection, publishConnection] = await Promise.all([\n this.getConnection(this.consumeConnection),\n this.getConnection(this.publishConnection),\n ]);\n isConnected = consumeConnection.isConnected() && publishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected - false');\n return false;\n }\n try {\n const unRegisteredConsumers = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers');\n }\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.waitForConnect();\n\n await Promise.all(\n this.consumersToRegister.map((c) => channel.checkQueue(c.queue)),\n );\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false', { msg: e.message });\n return false;\n }\n }\n // TODO:[QUORUM-PHASE-3] Delete the old is connected and adjust the return value to return true\n isConnected = await this.isConnectedOld();\n }\n\n this.#logger.debug(`rabbit: isConnected - ${isConnected}`);\n return isConnected;\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.gracefulShutdownStarted = true;\n const tagsNumber = this.consumersTags.size + this.oldConsumersTags.size;\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);\n const cancelTagPromises = [...this.consumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n const cancelTagPromisesOld = [...this.oldConsumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n // Clean the array to avoid race\n this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n const rejected = results.filter((p) => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected}`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');\n }\n }\n\n private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueueOld(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers || {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch (e) {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue} old`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array old`);\n this.oldConsumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // TODO: [QUORUM-PHASE-3] Delete all the function under this line.\n async getNewChannelOld({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnectionOld(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n\n if (!localConnection) {\n throw new Error(`rabbit: couldnt get connection for new channel ${name}`);\n }\n\n const channel = localConnection?.createChannel({ ...options });\n once(channel, 'close').then((args) => {\n this.#logger.error(`rabbit: channel ${name} closed`);\n onClose?.(args);\n });\n try {\n await once(channel, 'connect');\n this.#logger.debug(`rabbit: channel ${name} CONNECTED`);\n return channel;\n } catch (err) {\n this.#logger.error(`rabbit: channel error ${name} error`, { err });\n throw err;\n }\n }\n\n async getConnectionOld(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map((e) => once(this.oldEm, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n\n return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = await connect(defaultUrls, { findServers });\n\n connection.amqpConnection = newConnection;\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.oldConsumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.oldConsumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.oldEm.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n private saveConsumerOld(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.oldConsumersToRegister.some((consumer) => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.oldConsumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n async assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.oldQueues[queueName]) {\n delete this.oldQueueSetupPromises[queueName];\n return this.oldQueues[queueName]!;\n }\n\n this.oldQueueSetupPromises[queueName] ||= this.setupQueueOld(queueName, options);\n return this.oldQueueSetupPromises[queueName]!;\n }\n\n async setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.oldPublishConnection;\n const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannelOld({ force: true, connection });\n await this.deleteQueueOld(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.oldQueues[queueName] = queue;\n return queue;\n }\n\n async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n if (this.oldPublishChannel && !force) {\n resolve(this.oldPublishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannelOld({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.oldPublishConnection === connection) {\n this.oldPublishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n private async deleteQueueOld(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n\n if (this.oldExchanges[exchangeName]) {\n delete this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n if (this.oldAssertExchangePromises[exchangeName]) {\n return this.oldAssertExchangePromises[exchangeName]!;\n }\n\n this.oldAssertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName]!;\n }\n\n async isConnectedOld(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return true;\n }\n this.#logger.debug('rabbit: start is connected old');\n const [oldConsumeConnection, oldPublishConnection] = await Promise.all([\n this.getConnectionOld(this.oldConsumeConnection),\n this.getConnectionOld(this.oldPublishConnection),\n ]);\n const isConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected old - false');\n return false;\n }\n\n try {\n const unRegisteredConsumersOld = this.consumersToRegister.filter((c) => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumersOld.length > 0) {\n const queueNames = unRegisteredConsumersOld.map((c) => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues old', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers old');\n }\n\n const channelOld = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await channelOld.waitForConnect();\n\n await Promise.all(\n this.oldConsumersToRegister.map((c) => channelOld.checkQueue(c.queue)),\n );\n return true;\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false old', { msg: e.message });\n return false;\n }\n }\n\n private maskURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n urlObj.username = '***';\n urlObj.password = '***';\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n}\n\nexport default RabbitMq;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "peerDependencies": {
66
66
  "@autofleet/logger": "*",
67
- "@autofleet/zehut": "^4",
67
+ "@autofleet/zehut": "^4.4.0",
68
68
  "jest": "*"
69
69
  },
70
70
  "peerDependenciesMeta": {
@@ -74,7 +74,7 @@
74
74
  },
75
75
  "devDependencies": {
76
76
  "@autofleet/logger": "4.0.6",
77
- "@autofleet/zehut": "^4.2.2",
77
+ "@autofleet/zehut": "^4.4.0",
78
78
  "@types/amqplib": "0.10.7",
79
79
  "@types/jest": "^29.5.12",
80
80
  "@types/node": "^20.14.11",