@autofleet/rabbit 5.9.0-beta-d063edda.0 → 5.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-BS7IKP_W.d.cts → index-CfFMOozm.d.cts} +4 -2
- package/dist/{index-Ckja-tW_.d.ts → index-DYivwPDT.d.ts} +4 -2
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mock/index.d.cts +1 -1
- package/dist/mock/index.d.ts +1 -1
- package/dist/mock/vitest.d.cts +1 -1
- package/dist/mock/vitest.d.ts +1 -1
- package/package.json +4 -4
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["logger: LoggerInstanceManager","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","CONSUMER_DEFAULT_OPTIONS: Options.Consume","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","message: TaskMessage","payload: PublishPayload","result: PublishResponse","env","outbreak","CONTEXTS_IDS_HEADER","INTERNAL_REQUEST_PATHS_HEADER","#abortNackPromises","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","EventEmitter","#logger","options","fallbackLogger","#initRedis","redisClient: ReturnType<typeof createClient> | undefined","getRedisInstance","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","channel: ChannelWrapper","queue: Replies.AssertQueue","releaseLock: (() => Promise<void>) | null","traceTypes","abortListener: Disposable | null","channel","e: RabbitError | any"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.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 interface 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 { Options } from 'amqplib';\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 CONSUMPTION_DURATION_HEADER = 'x-total-processing-duration-ms';\nexport const REDELIVERED_COUNT_HEADER = 'x-redelivered-count';\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 callNackOnAbort: 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\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 const CONNECTION_ROLE = {\n CONSUMER: 'consumer',\n PUBLISHER: 'publisher',\n} as const;\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 { 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\ntype TaskData = Record<string, any>;\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n delivery_mode: number;\n content_type: string;\n };\n routing_key: string;\n payload: string;\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 { addAbortListener, 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';\nimport type {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { createClient } from 'redis';\nimport { runWithLoggerContext, type LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n INTERNAL_REQUEST_PATHS_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 CONSUMPTION_DURATION_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n REDELIVERED_COUNT_HEADER,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n CONSUMER_DEFAULT_OPTIONS,\n CONNECTION_ROLE,\n} from './lib/consts';\nimport type {\n AssertExchangePromisesDictionary,\n CallbackFunction,\n ConnectionData,\n ConsumeMessageOrNull,\n ConsumeOptions,\n CustomMessageHeaders,\n ExchangesCache,\n Message,\n NackOptions,\n QueuesCache,\n QueueSetupPromisesDictionary,\n} from './lib/types';\n\ntype PublishOptions = NonNullable<Parameters<ChannelWrapper['publish']>[3]>;\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 MY_POD_NAME,\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 getRetriesCount(msg: ConsumeMessage): number;\n getTotalConsumptionDuration(msg: ConsumeMessage): number;\n stopAcceptingWork(): Promise<void>;\n drain(timeoutMs?: number, throwOnTimeout?: boolean): Promise<void>;\n startConsume(): Promise<void>;\n redisClient?: ReturnType<typeof createClient>;\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 closeConnectionOnGracefulShutdown?: boolean;\n /**\n * When false, calling consume() or consumeFromExchange() will only register\n * the consumer. Call startConsume() to start all registered consumers.\n * @default true\n */\n autoStartConsumers?: boolean;\n /**\n * Provide an Redis client. When set, redisConfig is ignored.\n */\n redisClient?: ReturnType<typeof createClient>;\n /**\n * Provide an identifier for the instance, e.g. service name.\n * Used for naming AMQP connections, channels, and consumer tags — makes instances identifiable in the RabbitMQ management UI and logs.\n * @default MY_POD_NAME env var or a random UUID if MY_POD_NAME is not set.\n */\n identifier?: string;\n}\n\ninterface newChannelOpts {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n}\n\ninterface assertChannelOpts {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ninterface 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?.id !== undefined ? { [USER_TRACING_HEADER]: user.id } : {}),\n ...(user?.contextIds !== undefined ? { [CONTEXTS_IDS_HEADER]: user.contextIds } : {}),\n ...(user?.requestedContextPaths !== undefined ? { [INTERNAL_REQUEST_PATHS_HEADER]: user.requestedContextPaths } : {}),\n ...(traceId !== undefined ? { [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 connectionRole: CONNECTION_ROLE.PUBLISHER,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n connectionRole: CONNECTION_ROLE.CONSUMER,\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 createClient>;\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: AfConsumer[] = [];\n\n private readonly pendingConsumers: (() => Promise<void>)[] = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n /** Count of active callbacks (more memory efficient than storing promises) */\n private activeCallbackCount = 0;\n\n /** Tracks in-flight abort-triggered nack promises so drain() can await them */\n readonly #abortNackPromises = new Set<Promise<void>>();\n\n public shutdownAbortController: AbortController = new AbortController();\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 connectionRole: CONNECTION_ROLE.PUBLISHER,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n connectionRole: CONNECTION_ROLE.CONSUMER,\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: AfConsumer[] = [];\n\n #logger: LoggerInstanceManager;\n\n readonly identifier: string;\n\n constructor(\n public readonly options: AfRabbitOptions = {},\n /** @deprecated Pass redisClient to the options object instead */\n private readonly redisConfig?: RedisConfig | undefined,\n ) {\n this.#logger = options?.logger ?? fallbackLogger;\n this.identifier = options?.identifier || MY_POD_NAME || randomUUID();\n\n const { redisClient, redisLock } = this.#initRedis(options, redisConfig);\n this.redisClient = redisClient;\n this.redisLock = redisLock;\n if (!this.options?.dontGracefulShutdown) {\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\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 #initRedis(\n options: AfRabbitOptions,\n redisConfig: RedisConfig | undefined,\n ): { redisClient: ReturnType<typeof createClient> | undefined; redisLock: ReturnType<typeof RedisLock> | undefined; } {\n let redisClient: ReturnType<typeof createClient> | undefined;\n\n if (!redisConfig && !options?.redisClient) {\n this.#logger.info('rabbit: No Redis config provided and no Redis client provided, disabling Redis features');\n return { redisClient: undefined, redisLock: undefined };\n }\n\n if (options?.redisClient) {\n this.#logger.info('rabbit: Using provided redis client');\n redisClient = options.redisClient;\n } else {\n this.#logger.info('rabbit: No redis client provided, creating new redis client');\n redisClient = getRedisInstance(redisConfig!).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n }\n\n return { redisClient, redisLock: RedisLock(redisClient) };\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 getRetriesCount(msg: ConsumeMessage): number {\n const retryCount = msg.properties.headers?.[RETRY_HEADER];\n return Number.parseInt(retryCount || '0', 10) || 0;\n }\n\n public getRedeliveredCount(msg: ConsumeMessage): number {\n const redeliveredCount = msg.properties.headers?.[REDELIVERED_COUNT_HEADER];\n return Number.parseInt(redeliveredCount || '0', 10) || 0;\n }\n\n public getTotalConsumptionDuration(msg: ConsumeMessage): number {\n const consumptionDuration = msg.properties.headers?.[CONSUMPTION_DURATION_HEADER];\n return consumptionDuration ? Number.parseInt(consumptionDuration, 10) : 0;\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> => {\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n 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 private executeSafely = async (fn: () => void | Promise<void>, context: string): Promise<void> => {\n try {\n await fn();\n } catch (e) {\n this.#logger.error(`rabbit: error in ${context}`, { error: e });\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 consumptionDuration,\n isAborted = false,\n nackContext,\n }: NackOptions & { isAborted?: boolean; consumptionDuration?: number; } = {}): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n\n const currentRetryCount = this.getRetriesCount(msg);\n const currentConsumptionDuration = this.getTotalConsumptionDuration(msg) ?? 0;\n const currentRedeliveredCount = this.getRedeliveredCount(msg);\n const updatedConsumptionDuration = currentConsumptionDuration + (consumptionDuration ?? 0);\n // when a message is aborted we will not send to dead queue\n const sendToDeadQueue = (skipRetry || currentRetryCount >= options.retries!) && !isAborted;\n this.#logger.info('nack message', {\n deliveryTag: msg.fields.deliveryTag,\n currentRetryCount,\n updatedConsumptionDuration,\n sendToDeadQueue,\n isAborted,\n });\n if (options.onNack) {\n void this.executeSafely(() => options.onNack!({\n msg: RabbitMq.parseMsg(msg),\n retryCount: currentRetryCount,\n remainingRetries: (options.retries ?? 0) - currentRetryCount,\n sendToDeadQueue,\n nackContext,\n }), 'onNack callback');\n }\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: isAborted ? currentRetryCount : currentRetryCount + 1,\n [CONSUMPTION_DURATION_HEADER]: updatedConsumptionDuration,\n [REDELIVERED_COUNT_HEADER]: isAborted ? currentRedeliveredCount + 1 : currentRedeliveredCount,\n }, options.isQuorumQueue);\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n 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 connectionRole,\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(\n defaultUrls,\n {\n findServers,\n connectionOptions: {\n clientProperties: {\n connection_name: `${this.identifier}:quorum:${connectionRole}`,\n },\n },\n },\n );\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, name });\n void 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 we already have a channel and not forcing refresh, return it directly in current async context\n if (this.publishChannel && !force) {\n return this.publishChannel;\n }\n\n // If we're currently setting up, wait for that setup\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n\n try {\n const channel = await this.getNewChannel({\n connection,\n ...(connection.connectionRole === CONNECTION_ROLE.PUBLISHER && { name: `publish:${this.identifier}:quorum` }),\n });\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 const startFn = async () => {\n this.saveConsumerOld(queue, callback, options);\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 if (this.options.autoStartConsumers !== false) {\n await startFn();\n } else {\n this.pendingConsumers.push(startFn);\n }\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, name: `consume:${this.identifier}:${queue}:quorum` });\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\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n return runWithLoggerContext(async () => {\n const startTime = Date.now();\n const getTotalTime = () => Date.now() - startTime;\n\n const {\n [TRACING_HEADER]: traceId,\n [USER_TRACING_HEADER]: userId,\n [AUTOMATION_ID_HEADER]: automationId,\n [CONTEXTS_IDS_HEADER]: userContextIds,\n [INTERNAL_REQUEST_PATHS_HEADER]: requestedContextPaths,\n } = msg.properties.headers ?? {};\n this.#logger.addToContext({ userId });\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, requestedContextPaths);\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 & { isAborted?: boolean; } = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n const consumptionDuration = getTotalTime();\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, {\n ...nackOptions,\n consumptionDuration,\n });\n };\n\n // Increment counter before callback starts\n this.activeCallbackCount++;\n let abortListener: Disposable | null = null;\n try {\n if (options?.callNackOnAbort) {\n abortListener = addAbortListener(this.shutdownAbortController.signal, () => {\n this.#logger.warn('rabbit: callback aborted', { uniqueId, deliveryTag: msg.fields.deliveryTag });\n const nackPromise = localNack(msg, { isAborted: true });\n this.#abortNackPromises.add(nackPromise);\n void nackPromise.finally(() => {\n this.#abortNackPromises.delete(nackPromise);\n });\n });\n }\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n this.shutdownAbortController.signal,\n );\n } catch {\n return await localNack(msg);\n } finally {\n // Decrement counter when callback completes (success or failure)\n this.activeCallbackCount--;\n if (abortListener) {\n abortListener[Symbol.dispose]();\n }\n }\n });\n },\n {\n ...CONSUMER_DEFAULT_OPTIONS,\n consumerTag: `${this.identifier}:${queue}:quorum`,\n },\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\n const startFn = async () => {\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 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-from-exchange:${this.identifier}:${exchange}:${queue}:quorum`,\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 this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-from-exchange:${this.identifier}:${exchange}:${queue}`,\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 if (this.options.autoStartConsumers !== false) {\n await startFn();\n } else {\n this.pendingConsumers.push(startFn);\n }\n }\n\n async startConsume(): Promise<void> {\n await Promise.all(this.pendingConsumers.map(fn => fn()));\n this.pendingConsumers.length = 0;\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 stopAcceptingWork(): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.#logger.info('rabbit: stop accepting work - canceling all 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 this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n\n const rejected = results.filter(p => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: stop accepting work - failed to cancel #${rejected.length} tags: ${rejected as any}`);\n } else {\n this.#logger.info('rabbit: stop accepting work - all tags successfully canceled.');\n }\n };\n\n /**\n * Waits for all in-flight consumer callbacks to complete.\n *\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 10000 = 10s)\n * @param throwOnTimeout - Whether to throw error on timeout (default: true)\n * @returns Promise that resolves when all callbacks complete or timeout occurs\n * @throws Error if timeout occurs and throwOnTimeout is true\n */\n async drain(timeoutMs = 10_000, throwOnTimeout = true): Promise<void> {\n const startTime = Date.now();\n const initialCount = this.activeCallbackCount;\n\n this.#logger.info('rabbit: [drain] waiting for active callbacks', {\n activeCallbackCount: initialCount,\n timeoutMs,\n });\n\n if (initialCount === 0) {\n this.#logger.info('rabbit: [drain] no active callbacks to drain');\n return;\n }\n\n // Poll the counter until it reaches 0 or timeout\n const checkInterval = 50; // Check every 50ms\n\n const publishedMessagesWaiting = this.publishChannel?.queueLength() ?? 0;\n if (publishedMessagesWaiting > 0) {\n this.#logger.warn('rabbit: [drain] there are still published messages waiting in the channel buffer', {\n publishedMessagesWaiting,\n });\n }\n\n while (this.activeCallbackCount > 0) {\n const elapsed = Date.now() - startTime;\n\n if (elapsed >= timeoutMs) {\n const remaining = this.activeCallbackCount;\n this.#logger.warn('rabbit: [drain] timeout waiting for callbacks', {\n duration: elapsed,\n remainingCallbacks: remaining,\n timeoutMs,\n });\n this.shutdownAbortController.abort(new Error(`Graceful shutdown initiated by drain timeout after ${elapsed}ms with ${remaining} callbacks still active`));\n // Wait for all abort-triggered nack operations to complete (sendToQueue + channel.ack)\n // before returning. This prevents the caller from closing connections while\n // a nack is still in flight, which would cause channel.ack to fail and\n // result in the message being both requeued and re-published (duplicate delivery).\n await Promise.allSettled([...this.#abortNackPromises]);\n if (throwOnTimeout) {\n throw new Error(`Drain timeout after ${timeoutMs}ms - ${remaining} callbacks still active`);\n }\n return;\n }\n\n // Wait before checking again (efficient polling)\n await new Promise(resolve => setTimeout(resolve, checkInterval));\n }\n\n const duration = Date.now() - startTime;\n this.#logger.info('rabbit: [drain] all callbacks completed', {\n duration,\n callbackCount: initialCount,\n });\n }\n\n async closeConnections(): Promise<void> {\n if (this.activeCallbackCount > 0) {\n this.#logger.warn('rabbit: closing connections received with active callbacks. not performing the close', { activeCallbackCount: this.activeCallbackCount });\n return;\n }\n // close the channels and connections\n\n this.#logger.info('rabbit: closing connections');\n const connections = [this.consumeConnection, this.publishConnection, this.oldConsumeConnection, this.oldPublishConnection];\n await Promise.allSettled(connections.map(async (conn) => {\n if (conn.amqpConnection) {\n try {\n await conn.amqpConnection.close();\n this.#logger.info('rabbit: connection closed successfully');\n } catch (e) {\n this.#logger.error('rabbit: error closing connection', { e });\n }\n }\n }));\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\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 await this.stopAcceptingWork();\n this.shutdownAbortController.abort(new Error(`Graceful shutdown initiated by signal: ${signal}`));\n // wait for 1 sec to allow aborted shutdown signal message to re-queue\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, callNackOnAbort,\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, name: `consume:${this.identifier}:${queue}` });\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 return runWithLoggerContext(async () => {\n const startTime = Date.now();\n const getTotalTime = () => Date.now() - startTime;\n\n const {\n [TRACING_HEADER]: traceId,\n [USER_TRACING_HEADER]: userId,\n [AUTOMATION_ID_HEADER]: automationId,\n [CONTEXTS_IDS_HEADER]: userContextIds,\n [INTERNAL_REQUEST_PATHS_HEADER]: requestedContextPaths,\n } = msg.properties.headers ?? {};\n this.#logger.addToContext({ userId });\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, requestedContextPaths);\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 & { isAborted?: boolean; } = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n const consumptionDuration = getTotalTime();\n await this.nack(\n confirmChannel, queue, optionsWithDefaults,\n { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, { ...nackOptions, consumptionDuration });\n };\n\n // Increment counter before callback starts\n this.activeCallbackCount++;\n let abortListener: Disposable | null = null;\n try {\n if (callNackOnAbort) {\n abortListener = addAbortListener(this.shutdownAbortController.signal, () => {\n this.#logger.info('rabbit: shutdown signal received, calling localNack for in-flight message', { uniqueId, deliveryTag: msg.fields.deliveryTag });\n const nackPromise = localNack(msg, { isAborted: true });\n this.#abortNackPromises.add(nackPromise);\n void nackPromise.finally(() => {\n this.#abortNackPromises.delete(nackPromise);\n });\n });\n }\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n this.shutdownAbortController.signal,\n );\n } catch {\n return await localNack(msg);\n } finally {\n // Decrement counter when callback completes (success or failure)\n this.activeCallbackCount--;\n if (abortListener) {\n abortListener?.[Symbol.dispose]();\n }\n }\n });\n },\n {\n ...CONSUMER_DEFAULT_OPTIONS,\n consumerTag: `${this.identifier}:${queue}`,\n },\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, name });\n void 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 connectionRole,\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 // @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 = connect(\n defaultUrls,\n {\n findServers,\n connectionOptions: {\n clientProperties: {\n connection_name: `${this.identifier}:${connectionRole}`,\n },\n },\n },\n );\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.oldPublishChannel && !force) {\n return this.oldPublishChannel;\n }\n\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n\n try {\n const channel = await this.getNewChannelOld({\n connection,\n ...(connection.connectionRole === CONNECTION_ROLE.PUBLISHER && { name: `publish:${this.identifier}` }),\n });\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.oldConsumersToRegister.filter(c => !this.oldConsumersTags.get(c.queue));\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 type ConsumerCallbackFunction = CallbackFunction;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["logger: LoggerInstanceManager","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","CONSUMER_DEFAULT_OPTIONS: Options.Consume","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","message: TaskMessage","payload: PublishPayload","result: PublishResponse","env","outbreak","CONTEXTS_IDS_HEADER","INTERNAL_REQUEST_PATHS_HEADER","#abortNackPromises","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","EventEmitter","#logger","options","fallbackLogger","#initRedis","redisClient: ReturnType<typeof createClient> | undefined","getRedisInstance","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","channel: ChannelWrapper","queue: Replies.AssertQueue","releaseLock: (() => Promise<void>) | null","traceTypes","abortListener: Disposable | null","channel","e: RabbitError | any"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.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 interface 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 { Options } from 'amqplib';\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 CONSUMPTION_DURATION_HEADER = 'x-total-processing-duration-ms';\nexport const REDELIVERED_COUNT_HEADER = 'x-redelivered-count';\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 callNackOnAbort: 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\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 const CONNECTION_ROLE = {\n CONSUMER: 'consumer',\n PUBLISHER: 'publisher',\n} as const;\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 { 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\ntype TaskData = Record<string, any>;\n\ninterface TaskMessage {\n task: string;\n id: string;\n args: TaskData[];\n}\n\ninterface PublishPayload {\n properties: {\n delivery_mode: number;\n content_type: string;\n };\n routing_key: string;\n payload: string;\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 { addAbortListener, 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';\nimport type {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { createClient } from 'redis';\nimport { runWithLoggerContext, type LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n INTERNAL_REQUEST_PATHS_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 CONSUMPTION_DURATION_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n REDELIVERED_COUNT_HEADER,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n CONSUMER_DEFAULT_OPTIONS,\n CONNECTION_ROLE,\n} from './lib/consts';\nimport type {\n AssertExchangePromisesDictionary,\n CallbackFunction,\n ConnectionData,\n ConsumeMessageOrNull,\n ConsumeOptions,\n CustomMessageHeaders,\n ExchangesCache,\n Message,\n NackOptions,\n QueuesCache,\n QueueSetupPromisesDictionary,\n} from './lib/types';\n\ntype PublishOptions = NonNullable<Parameters<ChannelWrapper['publish']>[3]>;\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 MY_POD_NAME,\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 getRetriesCount(msg: ConsumeMessage): number;\n getTotalConsumptionDuration(msg: ConsumeMessage): number;\n stopAcceptingWork(): Promise<void>;\n drain(timeoutMs?: number, throwOnTimeout?: boolean): Promise<void>;\n startConsume(): Promise<void>;\n redisClient?: ReturnType<typeof createClient>;\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 closeConnectionOnGracefulShutdown?: boolean;\n /**\n * When false, calling consume() or consumeFromExchange() will only register\n * the consumer. Call startConsume() to start all registered consumers.\n * @default true\n */\n autoStartConsumers?: boolean;\n /**\n * Provide an Redis client. When set, redisConfig is ignored.\n */\n redisClient?: ReturnType<typeof createClient>;\n /**\n * Provide an identifier for the instance, e.g. service name.\n * Used for naming AMQP connections, channels, and consumer tags — makes instances identifiable in the RabbitMQ management UI and logs.\n * @default MY_POD_NAME env var or a random UUID if MY_POD_NAME is not set.\n */\n identifier?: string;\n}\n\ninterface newChannelOpts {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\n connection: ConnectionData;\n}\n\ninterface assertChannelOpts {\n channelName?: string;\n force?: boolean;\n connection: ConnectionData;\n}\n\ninterface 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?.id !== undefined ? { [USER_TRACING_HEADER]: user.id } : {}),\n ...(user?.contextIds !== undefined ? { [CONTEXTS_IDS_HEADER]: user.contextIds } : {}),\n ...(user?.requestedContextPaths !== undefined ? { [INTERNAL_REQUEST_PATHS_HEADER]: user.requestedContextPaths } : {}),\n ...(traceId !== undefined ? { [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 connectionRole: CONNECTION_ROLE.PUBLISHER,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n connectionRole: CONNECTION_ROLE.CONSUMER,\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 createClient>;\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: AfConsumer[] = [];\n\n private readonly pendingConsumers: (() => Promise<void>)[] = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n /** Count of active callbacks (more memory efficient than storing promises) */\n private activeCallbackCount = 0;\n\n /** Tracks in-flight abort-triggered nack promises so drain() can await them */\n readonly #abortNackPromises = new Set<Promise<void>>();\n\n public shutdownAbortController: AbortController = new AbortController();\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 connectionRole: CONNECTION_ROLE.PUBLISHER,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n connectionRole: CONNECTION_ROLE.CONSUMER,\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: AfConsumer[] = [];\n\n #logger: LoggerInstanceManager;\n\n readonly identifier: string;\n\n constructor(\n public readonly options: AfRabbitOptions = {},\n /** @deprecated Pass redisClient to the options object instead */\n private readonly redisConfig?: RedisConfig | undefined,\n ) {\n this.#logger = options?.logger ?? fallbackLogger;\n this.identifier = options?.identifier || MY_POD_NAME || randomUUID();\n\n const { redisClient, redisLock } = this.#initRedis(options, redisConfig);\n this.redisClient = redisClient;\n this.redisLock = redisLock;\n if (!this.options?.dontGracefulShutdown) {\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\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 #initRedis(\n options: AfRabbitOptions,\n redisConfig: RedisConfig | undefined,\n ): { redisClient: ReturnType<typeof createClient> | undefined; redisLock: ReturnType<typeof RedisLock> | undefined; } {\n let redisClient: ReturnType<typeof createClient> | undefined;\n\n if (!redisConfig && !options?.redisClient) {\n this.#logger.info('rabbit: No Redis config provided and no Redis client provided, disabling Redis features');\n return { redisClient: undefined, redisLock: undefined };\n }\n\n if (options?.redisClient) {\n this.#logger.info('rabbit: Using provided redis client');\n redisClient = options.redisClient;\n } else {\n this.#logger.info('rabbit: No redis client provided, creating new redis client');\n redisClient = getRedisInstance(redisConfig!).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n }\n\n return { redisClient, redisLock: RedisLock(redisClient) };\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 getRetriesCount(msg: ConsumeMessage): number {\n const retryCount = msg.properties.headers?.[RETRY_HEADER];\n return Number.parseInt(retryCount || '0', 10) || 0;\n }\n\n public getRedeliveredCount(msg: ConsumeMessage): number {\n const redeliveredCount = msg.properties.headers?.[REDELIVERED_COUNT_HEADER];\n return Number.parseInt(redeliveredCount || '0', 10) || 0;\n }\n\n public getTotalConsumptionDuration(msg: ConsumeMessage): number {\n const consumptionDuration = msg.properties.headers?.[CONSUMPTION_DURATION_HEADER];\n return consumptionDuration ? Number.parseInt(consumptionDuration, 10) : 0;\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> => {\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n 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 private executeSafely = async (fn: () => void | Promise<void>, context: string): Promise<void> => {\n try {\n await fn();\n } catch (e) {\n this.#logger.error(`rabbit: error in ${context}`, { error: e });\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 consumptionDuration,\n isAborted = false,\n nackContext,\n error,\n }: NackOptions & { isAborted?: boolean; consumptionDuration?: number; } = {}): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n\n const currentRetryCount = this.getRetriesCount(msg);\n const currentConsumptionDuration = this.getTotalConsumptionDuration(msg) ?? 0;\n const currentRedeliveredCount = this.getRedeliveredCount(msg);\n const updatedConsumptionDuration = currentConsumptionDuration + (consumptionDuration ?? 0);\n // when a message is aborted we will not send to dead queue\n const sendToDeadQueue = (skipRetry || currentRetryCount >= options.retries!) && !isAborted;\n const nackLogMeta = {\n deliveryTag: msg.fields.deliveryTag,\n currentRetryCount,\n maxRetries: options.retries,\n updatedConsumptionDuration,\n sendToDeadQueue,\n isAborted,\n error,\n };\n\n if (sendToDeadQueue) {\n this.#logger.error('nack message - sent to dead-letter queue', nackLogMeta);\n } else if (isAborted) {\n // Requeued because of graceful shutdown, not a processing failure - keep it quiet.\n this.#logger.info('nack message - requeued after shutdown abort', nackLogMeta);\n } else {\n this.#logger.warn('nack message - requeued for retry', nackLogMeta);\n }\n if (options.onNack) {\n void this.executeSafely(() => options.onNack!({\n msg: RabbitMq.parseMsg(msg),\n retryCount: currentRetryCount,\n remainingRetries: (options.retries ?? 0) - currentRetryCount,\n sendToDeadQueue,\n nackContext,\n }), 'onNack callback');\n }\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: isAborted ? currentRetryCount : currentRetryCount + 1,\n [CONSUMPTION_DURATION_HEADER]: updatedConsumptionDuration,\n [REDELIVERED_COUNT_HEADER]: isAborted ? currentRedeliveredCount + 1 : currentRedeliveredCount,\n }, options.isQuorumQueue);\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n 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 connectionRole,\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(\n defaultUrls,\n {\n findServers,\n connectionOptions: {\n clientProperties: {\n connection_name: `${this.identifier}:quorum:${connectionRole}`,\n },\n },\n },\n );\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, name });\n void 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 we already have a channel and not forcing refresh, return it directly in current async context\n if (this.publishChannel && !force) {\n return this.publishChannel;\n }\n\n // If we're currently setting up, wait for that setup\n if (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n\n try {\n const channel = await this.getNewChannel({\n connection,\n ...(connection.connectionRole === CONNECTION_ROLE.PUBLISHER && { name: `publish:${this.identifier}:quorum` }),\n });\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 const startFn = async () => {\n this.saveConsumerOld(queue, callback, options);\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 if (this.options.autoStartConsumers !== false) {\n await startFn();\n } else {\n this.pendingConsumers.push(startFn);\n }\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, name: `consume:${this.identifier}:${queue}:quorum` });\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 (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n this.activeCallbackCount++;\n return runWithLoggerContext(async () => {\n const startTime = Date.now();\n const getTotalTime = () => Date.now() - startTime;\n\n const {\n [TRACING_HEADER]: traceId,\n [USER_TRACING_HEADER]: userId,\n [AUTOMATION_ID_HEADER]: automationId,\n [CONTEXTS_IDS_HEADER]: userContextIds,\n [INTERNAL_REQUEST_PATHS_HEADER]: requestedContextPaths,\n } = msg.properties.headers ?? {};\n this.#logger.addToContext({ userId });\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, requestedContextPaths);\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 & { isAborted?: boolean; } = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n const consumptionDuration = getTotalTime();\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, {\n ...nackOptions,\n consumptionDuration,\n });\n };\n\n let abortListener: Disposable | null = null;\n try {\n if (options?.callNackOnAbort) {\n abortListener = addAbortListener(this.shutdownAbortController.signal, () => {\n this.#logger.warn('rabbit: callback aborted', { uniqueId, deliveryTag: msg.fields.deliveryTag });\n const nackPromise = localNack(msg, { isAborted: true });\n this.#abortNackPromises.add(nackPromise);\n void nackPromise.finally(() => {\n this.#abortNackPromises.delete(nackPromise);\n });\n });\n }\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n this.shutdownAbortController.signal,\n );\n } catch (error) {\n return await localNack(msg, { error });\n } finally {\n if (abortListener) {\n abortListener[Symbol.dispose]();\n }\n }\n }).finally(() => {\n this.activeCallbackCount--;\n });\n },\n {\n ...CONSUMER_DEFAULT_OPTIONS,\n consumerTag: `${this.identifier}:${queue}:quorum`,\n },\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\n const startFn = async () => {\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 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-from-exchange:${this.identifier}:${exchange}:${queue}:quorum`,\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 this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-from-exchange:${this.identifier}:${exchange}:${queue}`,\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 if (this.options.autoStartConsumers !== false) {\n await startFn();\n } else {\n this.pendingConsumers.push(startFn);\n }\n }\n\n async startConsume(): Promise<void> {\n await Promise.all(this.pendingConsumers.map(fn => fn()));\n this.pendingConsumers.length = 0;\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 stopAcceptingWork(): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.#logger.info('rabbit: stop accepting work - canceling all 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 this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n\n const rejected = results.filter(p => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: stop accepting work - failed to cancel #${rejected.length} tags: ${rejected as any}`);\n } else {\n this.#logger.info('rabbit: stop accepting work - all tags successfully canceled.');\n }\n };\n\n /**\n * Waits for all in-flight consumer callbacks to complete.\n *\n * @param timeoutMs - Maximum time to wait in milliseconds (default: 10000 = 10s)\n * @param throwOnTimeout - Whether to throw error on timeout (default: true)\n * @returns Promise that resolves when all callbacks complete or timeout occurs\n * @throws Error if timeout occurs and throwOnTimeout is true\n */\n async drain(timeoutMs = 10_000, throwOnTimeout = true): Promise<void> {\n const startTime = Date.now();\n const initialCount = this.activeCallbackCount;\n\n this.#logger.info('rabbit: [drain] waiting for active callbacks', {\n activeCallbackCount: initialCount,\n timeoutMs,\n });\n\n if (initialCount === 0) {\n this.#logger.info('rabbit: [drain] no active callbacks to drain');\n return;\n }\n\n // Poll the counter until it reaches 0 or timeout\n const checkInterval = 50; // Check every 50ms\n\n const publishedMessagesWaiting = this.publishChannel?.queueLength() ?? 0;\n if (publishedMessagesWaiting > 0) {\n this.#logger.warn('rabbit: [drain] there are still published messages waiting in the channel buffer', {\n publishedMessagesWaiting,\n });\n }\n\n while (this.activeCallbackCount > 0) {\n const elapsed = Date.now() - startTime;\n\n if (elapsed >= timeoutMs) {\n const remaining = this.activeCallbackCount;\n this.#logger.warn('rabbit: [drain] timeout waiting for callbacks', {\n duration: elapsed,\n remainingCallbacks: remaining,\n timeoutMs,\n });\n this.shutdownAbortController.abort(new Error(`Graceful shutdown initiated by drain timeout after ${elapsed}ms with ${remaining} callbacks still active`));\n // Wait for all abort-triggered nack operations to complete (sendToQueue + channel.ack)\n // before returning. This prevents the caller from closing connections while\n // a nack is still in flight, which would cause channel.ack to fail and\n // result in the message being both requeued and re-published (duplicate delivery).\n await Promise.allSettled([...this.#abortNackPromises]);\n if (throwOnTimeout) {\n throw new Error(`Drain timeout after ${timeoutMs}ms - ${remaining} callbacks still active`);\n }\n return;\n }\n\n // Wait before checking again (efficient polling)\n await new Promise(resolve => setTimeout(resolve, checkInterval));\n }\n\n const duration = Date.now() - startTime;\n this.#logger.info('rabbit: [drain] all callbacks completed', {\n duration,\n callbackCount: initialCount,\n });\n }\n\n async closeConnections(): Promise<void> {\n if (this.activeCallbackCount > 0) {\n this.#logger.warn('rabbit: closing connections received with active callbacks. not performing the close', { activeCallbackCount: this.activeCallbackCount });\n return;\n }\n // close the channels and connections\n\n this.#logger.info('rabbit: closing connections');\n const connections = [this.consumeConnection, this.publishConnection, this.oldConsumeConnection, this.oldPublishConnection];\n await Promise.allSettled(connections.map(async (conn) => {\n if (conn.amqpConnection) {\n try {\n await conn.amqpConnection.close();\n this.#logger.info('rabbit: connection closed successfully');\n } catch (e) {\n this.#logger.error('rabbit: error closing connection', { e });\n }\n }\n }));\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\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 await this.stopAcceptingWork();\n this.shutdownAbortController.abort(new Error(`Graceful shutdown initiated by signal: ${signal}`));\n // wait for 1 sec to allow aborted shutdown signal message to re-queue\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, callNackOnAbort,\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, name: `consume:${this.identifier}:${queue}` });\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 (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n this.activeCallbackCount++;\n return runWithLoggerContext(async () => {\n const startTime = Date.now();\n const getTotalTime = () => Date.now() - startTime;\n\n const {\n [TRACING_HEADER]: traceId,\n [USER_TRACING_HEADER]: userId,\n [AUTOMATION_ID_HEADER]: automationId,\n [CONTEXTS_IDS_HEADER]: userContextIds,\n [INTERNAL_REQUEST_PATHS_HEADER]: requestedContextPaths,\n } = msg.properties.headers ?? {};\n this.#logger.addToContext({ userId });\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, requestedContextPaths);\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 & { isAborted?: boolean; } = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n const consumptionDuration = getTotalTime();\n await this.nack(\n confirmChannel, queue, optionsWithDefaults,\n { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, { ...nackOptions, consumptionDuration });\n };\n\n let abortListener: Disposable | null = null;\n try {\n if (callNackOnAbort) {\n abortListener = addAbortListener(this.shutdownAbortController.signal, () => {\n this.#logger.info('rabbit: shutdown signal received, calling localNack for in-flight message', { uniqueId, deliveryTag: msg.fields.deliveryTag });\n const nackPromise = localNack(msg, { isAborted: true });\n this.#abortNackPromises.add(nackPromise);\n void nackPromise.finally(() => {\n this.#abortNackPromises.delete(nackPromise);\n });\n });\n }\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n this.shutdownAbortController.signal,\n );\n } catch (error) {\n return await localNack(msg, { error });\n } finally {\n if (abortListener) {\n abortListener?.[Symbol.dispose]();\n }\n }\n }).finally(() => {\n this.activeCallbackCount--;\n });\n },\n {\n ...CONSUMER_DEFAULT_OPTIONS,\n consumerTag: `${this.identifier}:${queue}`,\n },\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, name });\n void 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 connectionRole,\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 // @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 = connect(\n defaultUrls,\n {\n findServers,\n connectionOptions: {\n clientProperties: {\n connection_name: `${this.identifier}:${connectionRole}`,\n },\n },\n },\n );\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.oldPublishChannel && !force) {\n return this.oldPublishChannel;\n }\n\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n\n try {\n const channel = await this.getNewChannelOld({\n connection,\n ...(connection.connectionRole === CONNECTION_ROLE.PUBLISHER && { name: `publish:${this.identifier}` }),\n });\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.oldConsumersToRegister.filter(c => !this.oldConsumersTags.get(c.queue));\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 type ConsumerCallbackFunction = CallbackFunction;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as sendCeleryTaskViaHttp, i as RabbitMq, n as ConsumerCallbackFunction, r as IAfRabbitMq, t as AfRabbitOptions } from "./index-
|
|
1
|
+
import { a as sendCeleryTaskViaHttp, i as RabbitMq, n as ConsumerCallbackFunction, r as IAfRabbitMq, t as AfRabbitOptions } from "./index-CfFMOozm.cjs";
|
|
2
2
|
export { AfRabbitOptions, ConsumerCallbackFunction, IAfRabbitMq, RabbitMq as default, sendCeleryTaskViaHttp };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as sendCeleryTaskViaHttp, i as RabbitMq, n as ConsumerCallbackFunction, r as IAfRabbitMq, t as AfRabbitOptions } from "./index-
|
|
1
|
+
import { a as sendCeleryTaskViaHttp, i as RabbitMq, n as ConsumerCallbackFunction, r as IAfRabbitMq, t as AfRabbitOptions } from "./index-DYivwPDT.js";
|
|
2
2
|
export { AfRabbitOptions, ConsumerCallbackFunction, IAfRabbitMq, RabbitMq as default, sendCeleryTaskViaHttp };
|