@autofleet/rabbit 5.0.27 → 5.1.0-alpha.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","message: TaskMessage","payload: PublishPayload","result: PublishResponse","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","options","fallbackLogger","getRedisInstance","newConnection: AmqpConnectionManager","localConnection!: AmqpConnectionManager","channel: ChannelWrapper","queue: Replies.AssertQueue","releaseLock: (() => Promise<void>) | 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/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport 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 { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport type ExchangesCache = Record<string, Replies.AssertExchange | undefined>;\nexport type QueuesCache = Record<string, Replies.AssertQueue | undefined>;\nexport type QueueSetupPromisesDictionary = Record<string, Promise<Replies.AssertQueue> | undefined>;\nexport type AssertExchangePromisesDictionary = Record<string, Promise<Replies.AssertExchange> | undefined>;\n\nexport interface CustomMessageHeaders {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n // TODO: [QUORUM-PHASE-3] Redundant because all the queues are quorum queues\n isQuorumQueue?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport interface newChannelOpts {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport interface assertChannelOpts {\n channelName?: string;\n force?: boolean;\n}\nexport interface AfConsumer {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport interface ConnectionData {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n}\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\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 { 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 { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport type {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\n// TODO: [QUORUM-PHASE-3] Delete these env vars\nconst {\n DISABLE_QUORUM_QUEUES_CONSUME,\n DISABLE_QUORUM_QUEUES_PUBLISH,\n} = env;\n\nexport interface IAfRabbitMq {\n ack(channel: ConfirmChannel, msg: ConsumeMessageOrNull, shouldUpdateRedisTimestamp?: boolean, releaseLock?: (() => Promise<void>) | null): (userMsg: ConsumeMessage) => Promise<void>;\n nack(\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: () => Promise<void>,\n ): (userMsg: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>;\n assertChannel(options?: assertChannelOpts): Promise<ChannelWrapper>;\n assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange>;\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>;\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\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_TRACING_HEADER]: user?.id,\n [CONTEXTS_IDS_HEADER]: user?.contextIds,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n publishChannel: ChannelWrapper | null = null;\n\n publishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly publishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'publishConnectionCreated',\n connectionFailedEventName: 'publishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly consumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'consumeConnectionCreated',\n connectionFailedEventName: 'consumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly em: EventEmitter = new EventEmitter();\n\n readonly exchanges: ExchangesCache = {};\n\n readonly queues: QueuesCache = {};\n\n readonly queueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly assertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n /** A map of consumers' tags used for canceling consumption */\n readonly consumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string; }> = new Map<string, { channel: ConfirmChannel; consumerTag: string; }>();\n\n private readonly consumersToRegister: AfConsumer[] = [];\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n // TODO:[QUORUM-PHASE-3] Delete the old properties that we use for the old consumers and publishers\n oldPublishChannel: ChannelWrapper | null = null;\n\n oldPublishChannelSetupPromise: Promise<ChannelWrapper> | null = null;\n\n readonly oldPublishConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldPublishConnectionCreated',\n connectionFailedEventName: 'oldPublishConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldConsumeConnection: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: 'oldConsumeConnectionCreated',\n connectionFailedEventName: 'oldConsumeConnectionFailed',\n blockReconnect: false,\n };\n\n readonly oldEm: EventEmitter = new EventEmitter();\n\n readonly oldExchanges: ExchangesCache = {};\n\n readonly oldQueues: QueuesCache = {};\n\n readonly oldQueueSetupPromises: QueueSetupPromisesDictionary = {};\n\n readonly oldAssertExchangePromises: AssertExchangePromisesDictionary = {};\n\n readonly oldConsumersTags: Map<string, { channel: ConfirmChannel; consumerTag: string; }> = new Map<string, { channel: ConfirmChannel; consumerTag: string; }>();\n\n private readonly oldConsumersToRegister: AfConsumer[] = [];\n\n #logger: LoggerInstanceManager;\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger ?? fallbackLogger;\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map(e => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n return [`amqp://${userName}:${password}@${host}/${this.vhost}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.consumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err, advice: 'Check if the vhost exist', vhost: this.vhost });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.consumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.em.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n 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 (this.publishChannelSetupPromise) {\n return this.publishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.publishChannelSetupPromise = promise;\n if (this.publishChannel && !force) {\n resolve(this.publishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannel({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.publishConnection === connection) {\n this.publishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n async assertExchange(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n\n if (this.exchanges[exchangeName]) {\n delete this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName];\n }\n\n if (this.assertExchangePromises[exchangeName]) {\n return this.assertExchangePromises[exchangeName];\n }\n\n this.assertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.exchanges[exchangeName] = await this.assertExchangePromises[exchangeName];\n return this.exchanges[exchangeName];\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const { publishChannel: channel } = this;\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n this.#logger.debug('rabbit: getting queue length', { queue, connected: this.publishConnection.amqpConnection?.isConnected() });\n return channel?.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async bindQueue(queue: string, exchange: string): Promise<void> {\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.bindQueue(queue, exchange, ''));\n return channel.bindQueue(queue, exchange, '');\n }\n\n async setupQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.publishConnection;\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': 'quorum',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannel({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup(async (setupChannel: ConfirmChannel) => {\n await setupChannel.assertQueue(queueName, localeOptions);\n });\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannel({ force: true, connection });\n await this.deleteQueue(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.queues[queueName] = queue;\n return queue;\n }\n\n // TODO: [QUORUM-PHASE-3] Can be deleted after deleting the old consumers and publishers because all the queues are created us quorum queues\n static shouldUseQuorum(queueName: string): boolean {\n const envQuorumQueuesWhitelist = process.env.QUORUM_QUEUES_WHITELIST;\n\n if (envQuorumQueuesWhitelist === '*') {\n return true;\n }\n\n if (envQuorumQueuesWhitelist) {\n const whitelist = envQuorumQueuesWhitelist.split(',');\n return whitelist.includes(queueName);\n }\n\n return false;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.queues[queueName]) {\n delete this.queueSetupPromises[queueName];\n return this.queues[queueName];\n }\n\n this.queueSetupPromises[queueName] ??= this.setupQueue(queueName, options);\n return this.queueSetupPromises[queueName];\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.consumersToRegister.some(consumer => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.consumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n // Used by the microservices to consume messages from the queue\n async consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n this.saveConsumerOld(queue, callback, options);\n\n // TODO: [QUORUM-PHASE-3] Use only the implementation of consumeNew and delete consumeNew and consumeOld\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n await this.consumeNew(queue, callback, options);\n }\n await this.consumeOld(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeNew we do not use it anymore\n async consumeNew(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbit(queue, callback, options);\n }\n\n // TODO: [QUORUM-PHASE-3] Delete consumeOld we do not use it anymore\n async consumeOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n await this.consumeFromRabbitOld(queue, callback, options);\n }\n\n private async lockRedisIfNeeded(msg: ReturnType<typeof RabbitMq.parseMsg>, options: ConsumeOptions): Promise<(() => Promise<void>) | null> {\n const { properties: { headers } } = msg;\n const timestamp = headers?.creationTimestamp;\n let releaseLock: (() => Promise<void>) | null = null;\n\n if (options.useConsumeWithLock && timestamp && headers?.redisTimestampValidationKey && this.redisLock) {\n releaseLock = await this.redisLock(\n headers.redisTimestampValidationKey,\n options?.lockTimeout || DEFAULT_LOCK_TIMEOUT,\n );\n }\n return releaseLock;\n }\n\n private async unlockRedisIfNeeded(releaseLock?: (() => Promise<void>) | null): Promise<void> {\n if (this.redisLock && releaseLock) {\n await releaseLock();\n }\n }\n\n private async consumeFromRabbit(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannel({ connection: this.consumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array.`);\n this.consumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // Used by the microservices to consume messages from the exchange\n async consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n // TODO: [QUORUM-PHASE-3] Delete the if statement after all the queues are created as quorum queues\n if (options?.isQuorumQueue !== false && DISABLE_QUORUM_QUEUES_CONSUME !== 'true') {\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await this.saveConsumer(queue, callback, options);\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: this.consumeConnection,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.exchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeNew(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await this.saveConsumerOld(queue, callback, options);\n const channelOld: ChannelWrapper = await this.getNewChannelOld({\n name: `consume-exchange-${exchange}-queue-${queue}-old`,\n connection: this.oldConsumeConnection,\n });\n await channelOld.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n this.oldExchanges[exchange] = assertExchange;\n await c.prefetch(limit!, false);\n return Promise.all([\n c.bindQueue(queue, exchange, ''),\n this.consumeOld(\n queue,\n callback,\n options,\n ),\n ]);\n });\n }\n\n // Used by the microservices to publish messages to the exchange\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], isQuorumQueue = true): Promise<void> {\n await setImmediate();\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n await this.assertVHost();\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await this.assertExchange(exchange, this.publishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n return;\n }\n\n // TODO: [QUORUM-PHASE-3] Delete the old implementation\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection: this.oldPublishConnection });\n await this.assertExchangeOld(exchange, this.oldPublishConnection);\n await channel.publish(exchange, '', Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n }\n\n // Used by the microservices to send messages to the queue\n // TODO: [QUORUM-PHASE-3] isQuorumQueue flag is not needed anymore because all the queues are created as quorum queues\n async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n isQuorumQueue = true,\n ): Promise<boolean | undefined> {\n if (isQuorumQueue && DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n try {\n await this.assertVHost();\n await this.assertChannel({ connection: this.publishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueue(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.publishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnected();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n } else {\n try {\n await this.assertChannelOld({ connection: this.oldPublishConnection });\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to send assert channel when sending to queue ${queue}`, { e });\n throw e;\n }\n\n try {\n RabbitMq.validateName('queue', queue);\n await this.assertQueueOld(queue, options);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to assert queue ${queue}`, { e });\n throw e;\n }\n\n try {\n const res = await this.oldPublishChannel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue}`, { res });\n return res;\n } catch (e) {\n const isConnected = await this.isConnectedOld();\n this.#logger.error(`rabbit sendToQueue: failed to send to queue ${queue}, isConnected: ${isConnected}`, { e });\n throw e;\n }\n }\n }\n\n async isConnected(): Promise<boolean> {\n let isConnected = true;\n // TODO:[QUORUM-PHASE-3] Remove the condition\n if (!this.gracefulShutdownStarted) {\n if (DISABLE_QUORUM_QUEUES_CONSUME !== 'true' || DISABLE_QUORUM_QUEUES_PUBLISH !== 'true') {\n this.#logger.debug('rabbit: start is connected');\n const [consumeConnection, publishConnection] = await Promise.all([\n this.getConnection(this.consumeConnection),\n this.getConnection(this.publishConnection),\n ]);\n isConnected = consumeConnection.isConnected() && publishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected - false');\n return false;\n }\n try {\n const unRegisteredConsumers = this.consumersToRegister.filter(c => !this.consumersTags.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map(c => c.queue);\n\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n count: queueNames.length,\n queues: queueNames,\n });\n throw new RabbitError('Found unregistered consumers');\n }\n const channel: ChannelWrapper = await this.assertChannel({ connection: this.publishConnection });\n await channel.waitForConnect();\n\n await Promise.all(\n this.consumersToRegister.map(c => channel.checkQueue(c.queue)),\n );\n } catch (e: RabbitError | any) {\n this.#logger.error('rabbit: isConnected - false', { msg: e.message });\n return false;\n }\n }\n // TODO:[QUORUM-PHASE-3] Delete the old is connected and adjust the return value to return true\n isConnected = await this.isConnectedOld();\n }\n\n this.#logger.debug(`rabbit: isConnected - ${isConnected}`);\n return isConnected;\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n // TODO: [QUORUM-PHASE-3] Delete the old implementation they are not needed anymore\n this.gracefulShutdownStarted = true;\n const tagsNumber = this.consumersTags.size + this.oldConsumersTags.size;\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${tagsNumber} tags...`);\n const cancelTagPromises = [...this.consumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n const cancelTagPromisesOld = [...this.oldConsumersTags].map(\n ([, { channel, consumerTag }]) => channel.cancel(consumerTag),\n );\n // Clean the array to avoid race\n this.consumersTags.clear();\n this.oldConsumersTags.clear();\n const results = await Promise.allSettled([...cancelTagPromises, ...cancelTagPromisesOld]);\n const rejected = results.filter(p => p.status === 'rejected');\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${tagsNumber} tags failed to cancel: ${rejected as any}`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all tags successfully canceled.');\n }\n }\n\n private async consumeFromRabbitOld(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void> {\n const optionsWithDefaults = { ...DEFAULT_OPTIONS, ...options };\n RabbitMq.validateName('queue', queue);\n const uniqueId = randomUUID();\n const {\n limit, deadMessageTtl, useConsumeWithLock, lockTimeout, auditContext, enableRabbitTrace,\n } = optionsWithDefaults;\n if (useConsumeWithLock) {\n if (!this.redisLock) {\n throw new RabbitError('Usage of consumeWithLock requires RedisInstance');\n }\n this.#logger.info(`rabbit: Consuming with lock from queue ${queue} with lockTimeout: ${lockTimeout}ms`);\n }\n const channel = await this.getNewChannelOld({ connection: this.oldConsumeConnection });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueueOld(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue} old`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array old`);\n this.oldConsumersTags.set(queue, { channel: confirmChannel, consumerTag });\n }\n });\n }\n\n // TODO: [QUORUM-PHASE-3] Delete all the function under this line.\n async getNewChannelOld({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnectionOld(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n\n if (!localConnection) {\n throw new Error(`rabbit: couldnt get connection for new channel ${name}`);\n }\n\n const channel = localConnection?.createChannel({ ...options });\n 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 } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map(e => once(this.oldEm, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT });\n\n return [`amqp://${userName}:${password}@${host}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n // eslint-disable-next-line @typescript-eslint/await-thenable\n const newConnection: AmqpConnectionManager = await connect(defaultUrls, { findServers });\n\n connection.amqpConnection = newConnection;\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n this.oldConsumersTags.clear();\n if (typeof err.url === 'string') {\n err.url = this.maskURL(err.url);\n }\n this.#logger.error('rabbit: connection connectFailed', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.oldEm.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('disconnect', ({ err }) => {\n this.oldConsumersTags.clear();\n this.#logger.debug('rabbit: connection closed');\n if (this.options?.disableReconnect) {\n this.#logger.error(`${this.DISCONNECT_MSG}${err && ` - ${err}`}`);\n connection.blockReconnect = true;\n } else {\n this.#logger.error(`${this.RECONNECT_MSG}${err && ` - ${err}`}`);\n }\n });\n\n newConnection.once('connect', async () => {\n this.#logger.debug('rabbit: connection established');\n connection.creatingConnection = false;\n this.oldEm.emit(connectionCreatedEventName, newConnection);\n isResolved = true;\n resolve(newConnection);\n });\n\n return promise;\n }\n\n private saveConsumerOld(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined): void {\n const isConsumerExist: boolean = this.oldConsumersToRegister.some(consumer => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array`);\n this.oldConsumersToRegister.push({\n queue,\n callback,\n options,\n });\n }\n }\n\n async assertQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n if (this.oldQueues[queueName]) {\n delete this.oldQueueSetupPromises[queueName];\n return this.oldQueues[queueName];\n }\n\n this.oldQueueSetupPromises[queueName] ??= this.setupQueueOld(queueName, options);\n return this.oldQueueSetupPromises[queueName];\n }\n\n async setupQueueOld(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n const connection = this.oldPublishConnection;\n const shouldUseQuorum = RabbitMq.shouldUseQuorum(queueName);\n const localeOptions = {\n ...options,\n durable: true,\n arguments: {\n ...options?.arguments,\n 'x-consumer-timeout': 1000 * 60 * 60 * 24,\n 'x-queue-type': shouldUseQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.debug('assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } catch (e) {\n this.#logger.error('rabbit: assertQueue error', { queueName, options, error: e });\n if (!this.options?.dontRetryAssert) {\n this.#logger.debug('retrying assertQueue', { queueName });\n const channel = await this.assertChannelOld({ force: true, connection });\n await this.deleteQueueOld(queueName, connection);\n\n this.#logger.debug('retrying assertQueue->channel.addSetup', { queueName });\n await channel.addSetup((setupChannel: ConfirmChannel) => setupChannel.assertQueue(queueName, localeOptions));\n this.#logger.debug('retrying assertQueue->channel.assertQueue', { queueName });\n queue = await channel.assertQueue(queueName, localeOptions);\n } else {\n throw e;\n }\n }\n\n this.oldQueues[queueName] = queue;\n return queue;\n }\n\n async assertChannelOld({ force = false, connection }: assertChannelOpts): Promise<ChannelWrapper> {\n if (this.oldPublishChannelSetupPromise) {\n return this.oldPublishChannelSetupPromise;\n }\n const { promise, resolve, reject } = createDeferredPromise<ChannelWrapper>();\n this.oldPublishChannelSetupPromise = promise;\n if (this.oldPublishChannel && !force) {\n resolve(this.oldPublishChannel);\n return promise;\n }\n\n try {\n const channel = await this.getNewChannelOld({ connection });\n channel.on('error', (err) => {\n this.#logger.error('rabbit: channel error', { err });\n });\n if (this.oldPublishConnection === connection) {\n this.oldPublishChannel = channel;\n }\n resolve(channel);\n } catch (e) {\n reject(e);\n }\n return promise;\n }\n\n private async deleteQueueOld(queue: string, connection: ConnectionData): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n this.#logger.info('rabbit: deleting queue', { queue });\n const deleteQueueRes = await channel.deleteQueue(queue);\n this.#logger.debug('queue deleted', deleteQueueRes);\n return deleteQueueRes;\n }\n\n async assertExchangeOld(exchangeName: string, connection: ConnectionData): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelOld({ connection });\n\n if (this.oldExchanges[exchangeName]) {\n delete this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName];\n }\n\n if (this.oldAssertExchangePromises[exchangeName]) {\n return this.oldAssertExchangePromises[exchangeName];\n }\n\n this.oldAssertExchangePromises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n this.oldExchanges[exchangeName] = await this.oldAssertExchangePromises[exchangeName];\n return this.oldExchanges[exchangeName];\n }\n\n async isConnectedOld(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return true;\n }\n this.#logger.debug('rabbit: start is connected old');\n const [oldConsumeConnection, oldPublishConnection] = await Promise.all([\n this.getConnectionOld(this.oldConsumeConnection),\n this.getConnectionOld(this.oldPublishConnection),\n ]);\n const isConnected = oldConsumeConnection.isConnected() && oldPublishConnection.isConnected();\n if (!isConnected) {\n this.#logger.error('rabbit: isConnected old - false');\n return false;\n }\n\n try {\n const unRegisteredConsumersOld = this.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 {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","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","resolve!: PromiseWithResolvers<T>['resolve']","reject!: PromiseWithResolvers<T>['reject']","CONSUMER_DEFAULT_OPTIONS: Options.Consume","message: TaskMessage","payload: PublishPayload","result: PublishResponse","options: AfRabbitOptions","redisConfig?: RedisConfig | undefined","#logger","options","fallbackLogger","getRedisInstance","newConnection: AmqpConnectionManager","connectionData: ConnectionData","connectionData","localConnection!: AmqpConnectionManager","channel: ChannelWrapper","promises","queue: Replies.AssertQueue","setupPromises","releaseLock: (() => Promise<void>) | null","e: RabbitError | any","cancelPromises: Promise<unknown>[]"],"sources":["../src/logger.ts","../src/lib/rabbitError.ts","../src/lib/redis.ts","../src/lib/consts.ts","../src/lib/utils.ts","../src/lib/types.ts","../src/lib/celery.ts","../src/index.ts"],"sourcesContent":["import Logger, { type LoggerInstanceManager } from '@autofleet/logger';\n\nconst logger: LoggerInstanceManager = Logger();\n\nexport default logger;\n","export default class RabbitError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RabbitError';\n }\n}\n","import { createClient } from 'redis';\n\nexport 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 { ConsumeOptions } from './types';\n\nexport const DEFAULT_DEAD_TTL_TWO_DAYS: number = 60_000 * 60 * 12;\nexport const DEFAULT_LOCK_TIMEOUT: number = 1000 * 5;\nexport const RETRY_HEADER = 'x-retry-count';\nexport const TRACING_HEADER = 'x-trace-id';\nexport const USER_TRACING_HEADER = 'x-af-user-id';\nexport const AUTOMATION_ID_HEADER = 'x-af-automation-id';\nexport const USER_OBJECT = 'userObject';\nexport const DEFAULT_USE_CONSUME_WITH_LOCK = false;\nexport const DEFAULT_OPTIONS: ConsumeOptions = {\n limit: 1,\n retries: 1,\n deadMessageTtl: DEFAULT_DEAD_TTL_TWO_DAYS,\n lockTimeout: DEFAULT_LOCK_TIMEOUT,\n useConsumeWithLock: DEFAULT_USE_CONSUME_WITH_LOCK,\n auditContext: null,\n enableRabbitTrace: false,\n} satisfies ConsumeOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG: BackoffOptions = {\n startingDelay: 500,\n timeMultiple: 4,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n\nexport const ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG: BackoffOptions = {\n startingDelay: 1,\n timeMultiple: 1,\n numOfAttempts: 5,\n} satisfies BackoffOptions;\n","import type { ConfirmChannel, Replies } from 'amqplib';\nimport type { ChannelWrapper } from 'amqp-connection-manager';\nimport type { BackoffOptions } from 'exponential-backoff';\nimport { ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG, ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG } from './consts';\n\nconst { PROJECT_ID } = process.env;\n\nexport const assertExchangeFanout = async (\n c: ChannelWrapper | ConfirmChannel,\n exchangeName: string,\n): Promise<Replies.AssertExchange> => c.assertExchange(exchangeName, 'fanout');\n\nexport const rand = (): number => Math.floor(Math.random() * 100_000);\n\ninterface PromiseWithResolvers<T> {\n promise: Promise<T>;\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: any) => void;\n}\ninterface PromiseCls extends PromiseConstructor {\n withResolvers<T>(): PromiseWithResolvers<T>;\n}\n/** This is polyfill for `Promise.withResolvers` which exists only on Node v22 and onwards */\nexport const createDeferredPromise = <T = void>(): PromiseWithResolvers<T> => {\n if ((Promise as PromiseCls).withResolvers) {\n return (Promise as PromiseCls).withResolvers<T>();\n }\n let resolve!: PromiseWithResolvers<T>['resolve'];\n let reject!: PromiseWithResolvers<T>['reject'];\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n};\n\nconst isDevEnv = (): boolean => ['af-experiment-manager', 'dev1-experiment-manager'].includes(PROJECT_ID || '');\n\nexport const getAssertVhostExponentialBackoffConfig = (): BackoffOptions => (\n isDevEnv()\n ? ASSERT_VHOST_EXPONENTIAL_BACKOFF_DEV_ENV_CONFIG\n : ASSERT_VHOST_EXPONENTIAL_BACKOFF_PROD_CONFIG);\n","import type { AmqpConnectionManager } from 'amqp-connection-manager';\nimport type { ConsumeMessage, Options, Replies } from 'amqplib';\n\nexport type ExchangesCache = Record<string, Replies.AssertExchange | undefined>;\nexport type QueuesCache = Record<string, Replies.AssertQueue | undefined>;\nexport type QueueSetupPromisesDictionary = Record<string, Promise<Replies.AssertQueue> | undefined>;\nexport type AssertExchangePromisesDictionary = Record<string, Promise<Replies.AssertExchange> | undefined>;\n\nexport interface CustomMessageHeaders {\n redisTimestampValidationKey?: string;\n}\nexport type ConsumeMessageOrNull = ConsumeMessage | null;\n\nexport interface ConsumeOptions {\n retries?: number;\n deadMessageTtl?: number;\n messageTtl?: number;\n limit?: number;\n lockTimeout?: number;\n useConsumeWithLock?: boolean;\n auditContext?: any;\n enableRabbitTrace?: boolean;\n}\n\nexport interface NackOptions {\n skipRetry?: boolean;\n}\n\nexport type Message = Omit<ConsumeMessage, 'content'> & { content: any; };\n\nexport type CallbackFunction = (msg: Message, ack: () => Promise<void>, nack: (ignored: ConsumeMessageOrNull, nackOptions?: NackOptions) => Promise<void>) => Promise<void>;\n\nexport interface newChannelOpts {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n};\nexport interface assertChannelOpts {\n channelName?: string;\n force?: boolean;\n}\nexport interface AfConsumer {\n queue: string;\n callback: CallbackFunction;\n options: ConsumeOptions | undefined;\n}\n\nconst HA_PROMOTE_ON_FAILURE = 'ha-promote-on-failure';\n\nconst HA_PROMOTE_ON_SHUTDOWN = 'ha-promote-on-shutdown';\n\nexport const CONSUMER_DEFAULT_OPTIONS: Options.Consume = {\n arguments: {\n [HA_PROMOTE_ON_FAILURE]: 'always',\n [HA_PROMOTE_ON_SHUTDOWN]: 'always',\n },\n};\n\nexport interface ConnectionData {\n amqpConnection: AmqpConnectionManager | null;\n creatingConnection: boolean;\n connectionCreatedEventName: string;\n connectionFailedEventName: string;\n blockReconnect: boolean;\n}\n","import { randomUUID } from 'node:crypto';\nimport logger from '../logger';\n// Environment configuration\nconst config = {\n host: process.env.RABBITMQ_SERVICE_HOST || 'localhost',\n username: process.env.RABBITMQ_USERNAME || 'guest',\n password: process.env.RABBITMQ_PASSWORD || 'guest',\n} as const;\n\n// Type definitions\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 { setImmediate } from 'node:timers/promises';\nimport { EventEmitter, once } from 'node:events';\nimport moment from 'moment';\nimport RedisLock from 'redis-lock';\nimport {\n type AmqpConnectionManager, type ChannelWrapper, connect, type CreateChannelOpts,\n} from 'amqp-connection-manager';\nimport type { PublishOptions } from 'amqp-connection-manager/dist/types/ChannelWrapper';\nimport type {\n ConfirmChannel, ConsumeMessage, Options, Replies,\n} from 'amqplib';\nimport { backOff } from 'exponential-backoff';\nimport type { LoggerInstanceManager } from '@autofleet/logger';\nimport {\n getUser,\n newTrace,\n traceTypes,\n createOrSetRabbitTrace,\n outbreak,\n CONTEXTS_IDS_HEADER,\n} from '@autofleet/zehut';\nimport { randomUUID } from 'node:crypto';\nimport fallbackLogger from './logger';\nimport RabbitError from './lib/rabbitError';\nimport getRedisInstance, { type RedisConfig } from './lib/redis';\nimport {\n assertExchangeFanout, createDeferredPromise, getAssertVhostExponentialBackoffConfig, rand,\n} from './lib/utils';\nimport {\n AUTOMATION_ID_HEADER,\n DEFAULT_LOCK_TIMEOUT,\n DEFAULT_OPTIONS,\n RETRY_HEADER,\n TRACING_HEADER,\n USER_TRACING_HEADER,\n} from './lib/consts';\nimport {\n type AssertExchangePromisesDictionary,\n type CallbackFunction,\n type ConnectionData,\n type ConsumeMessageOrNull,\n type ConsumeOptions,\n CONSUMER_DEFAULT_OPTIONS,\n type CustomMessageHeaders,\n type ExchangesCache,\n type Message,\n type NackOptions,\n type QueuesCache,\n type QueueSetupPromisesDictionary,\n} from './lib/types';\n\nconst PUBLISH_TIMEOUT = 1000 * 10;\n\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 assertExchange(exchangeName: string, vhost?: string): Promise<Replies.AssertExchange>;\n assertQueue(queueName: string, options?: Options.AssertQueue | null): Promise<Replies.AssertQueue>;\n consume(queue: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n consumeFromExchange(queue: string, exchange: string, callback: CallbackFunction, options?: ConsumeOptions): Promise<void>;\n publish(exchange: string, content: any, customHeaders?: PublishOptions['headers']): Promise<void>;\n sendToQueue(queue: string, content: any, options?: Options.AssertQueue | null, customHeaders?: PublishOptions['headers']): Promise<boolean | undefined>;\n redisClient?: ReturnType<typeof getRedisInstance>;\n}\n\nexport interface AfRabbitOptions {\n disableReconnect?: boolean;\n /**\n * When you want your own grace-full shutdown, set this to true.\n * @default false\n */\n dontGracefulShutdown?: boolean;\n /**\n * don't retry on creation error\n * @default false\n */\n dontRetryAssert?: boolean;\n rabbitHost?: string;\n vhost?: string;\n logger?: LoggerInstanceManager;\n}\n\ninterface newChannelOpts {\n name?: string;\n onClose?: null | ((args: any | null) => void);\n options?: CreateChannelOpts | undefined;\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_TRACING_HEADER]: user?.id,\n [CONTEXTS_IDS_HEADER]: user?.contextIds,\n [TRACING_HEADER]: traceId,\n },\n };\n }\n\n readonly DISCONNECT_MSG = 'rabbit: connection disconnect';\n\n readonly RECONNECT_MSG = 'rabbit: connection disconnect - reconnecting';\n\n readonly redisClient?: ReturnType<typeof getRedisInstance>;\n\n readonly redisLock?: ReturnType<typeof RedisLock>;\n\n private readonly em: EventEmitter = new EventEmitter();\n\n private doesVHostExist = false;\n\n private readonly vhost = 'quorum-vhost';\n\n private gracefulShutdownStarted = false;\n\n #logger: LoggerInstanceManager;\n\n private readonly quorumQueues: Set<string>;\n\n // New vhost-based connection pooling infrastructure\n private readonly publishConnections = new Map<string, ConnectionData>();\n\n private readonly consumeConnections = new Map<string, ConnectionData>();\n\n private readonly publishChannels = new Map<string, ChannelWrapper | null>();\n\n private readonly publishChannelSetupPromises = new Map<string, Promise<ChannelWrapper> | null>();\n\n // Vhost-aware caches\n private readonly queuesByVhost = new Map<string, QueuesCache>();\n\n private readonly exchangesByVhost = new Map<string, ExchangesCache>();\n\n private readonly queueSetupPromisesByVhost = new Map<string, QueueSetupPromisesDictionary>();\n\n private readonly assertExchangePromisesByVhost = new Map<string, AssertExchangePromisesDictionary>();\n\n private readonly consumersTagsByVhost = new Map<string, Map<string, { channel: ConfirmChannel; consumerTag: string; }>>();\n\n private readonly consumersToRegisterByVhost = new Map<string, AfConsumer[]>();\n\n constructor(public readonly options: AfRabbitOptions = {}, private readonly redisConfig?: RedisConfig | undefined) {\n this.#logger = options?.logger ?? fallbackLogger;\n\n // Parse QUORUM_QUEUES env var\n const quorumQueuesEnv = process.env.QUORUM_QUEUES || '';\n this.quorumQueues = new Set(\n quorumQueuesEnv.split(',')\n .map(q => q.trim())\n .filter(Boolean),\n );\n\n if (redisConfig) {\n this.redisClient = getRedisInstance(redisConfig).on('error', (err) => {\n this.#logger.error('rabbit: Redis error', { err, redisConfig });\n });\n this.redisClient.connect().catch((err) => {\n this.#logger.error('rabbit: Failed to connect to Redis', { err, redisConfig });\n });\n this.redisLock = RedisLock(this.redisClient);\n }\n this.#logger.info(`rabbit: [gracefully-shutdown] adding gracefully shutdown for process.pid ${process.pid}`);\n if (!this.options?.dontGracefulShutdown) {\n process.on('SIGTERM', async () => {\n await this.gracefulShutdown('SIGTERM');\n });\n process.on('SIGINT', async () => {\n await this.gracefulShutdown('SIGINT');\n });\n }\n }\n\n private getRedisKey(key: string): string {\n return `${this.redisConfig?.prefix || ''}${key}`;\n }\n\n private isQuorumQueue(queueName: string): boolean {\n return this.quorumQueues.has(queueName);\n }\n\n private getVhostForQueue(queueName: string): string {\n return this.isQuorumQueue(queueName) ? 'quorum-vhost' : '';\n }\n\n private assertVHost = async () => {\n if (this.doesVHostExist) {\n return;\n }\n\n const username = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const credentials = Buffer.from(`${username}:${password}`).toString('base64');\n const headers = {\n Authorization: `Basic ${credentials}`,\n 'Content-Type': 'application/json',\n };\n\n const rabbitHost = `http://${(this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost').split(':')[0]}:15672`;\n\n const url = `${rabbitHost}/api/vhosts/${encodeURIComponent(this.vhost)}`;\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers,\n });\n\n if (response.status === 200) {\n this.doesVHostExist = true;\n this.#logger.info('Vhost exists', { vhost: this.vhost });\n return;\n }\n\n if (response.status !== 404) {\n this.#logger.error('Failed to check vhost', { response });\n throw new RabbitError('Failed to check vhost');\n }\n\n const createResponse = await fetch(url, {\n method: 'PUT',\n headers,\n body: JSON.stringify({ default_queue_type: 'quorum' }),\n });\n\n if (!createResponse.ok) {\n this.#logger.error('Failed to create vhost', { response: createResponse });\n throw new RabbitError('Failed to create vhost');\n }\n\n this.doesVHostExist = true;\n this.#logger.info('Vhost created', { vhost: this.vhost });\n } catch (error) {\n this.#logger.error('Failed to check or create vhost', { error });\n throw error;\n }\n };\n\n private shouldConsumeMessageByTimestamp = async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return false;\n }\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n const lastMessageTimestamp = await this.redisClient.get(key);\n return !lastMessageTimestamp || (parseInt(lastMessageTimestamp, 10) <= parseInt(timestamp, 10));\n }\n return true;\n };\n\n public ack = (\n channel: ConfirmChannel,\n msg: ConsumeMessageOrNull,\n shouldUpdateRedisTimestamp = false,\n releaseLock: (() => Promise<void>) | null = null,\n ) => async (userMsg: ConsumeMessage): Promise<void> => { // eslint-disable-line @typescript-eslint/no-unused-vars\n if (!msg) {\n return;\n }\n this.#logger.debug('rabbit acking message', { deliveryTag: msg.fields.deliveryTag });\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await channel.ack(msg);\n const { headers } = msg.properties;\n const timestamp = headers?.creationTimestamp;\n\n if (shouldUpdateRedisTimestamp && timestamp && headers?.redisTimestampValidationKey && this.redisClient) {\n const parsedTimestamp = parseInt(timestamp, 10);\n const key = this.getRedisKey(headers.redisTimestampValidationKey);\n await this.redisClient.set(key, parsedTimestamp, { EX: 3600 });\n await this.unlockRedisIfNeeded(releaseLock);\n }\n };\n\n public nack = (\n channel: ConfirmChannel,\n queue: string,\n options: ConsumeOptions,\n deadQueueOptions: Options.AssertQueue,\n msg: ConsumeMessageOrNull,\n releaseLock?: (() => Promise<void>) | null,\n ) => async (\n userMsg: ConsumeMessageOrNull,\n {\n skipRetry = false,\n }: NackOptions = { },\n ): Promise<void> => {\n await this.unlockRedisIfNeeded(releaseLock);\n if (!channel || !msg) {\n this.#logger.error('no channel or msg', { msg });\n return;\n }\n const currentRetryHeader = Number.parseInt(msg.properties.headers?.[RETRY_HEADER] || '0', 10) || 0;\n const sendToDeadQueue = skipRetry || currentRetryHeader >= options.retries!;\n await this.sendToQueue(`${queue}${sendToDeadQueue ? '-dead' : ''}`, RabbitMq.parseMsg(msg).content, sendToDeadQueue ? deadQueueOptions : options, {\n ...msg.properties.headers,\n [RETRY_HEADER]: currentRetryHeader + 1,\n });\n this.#logger.debug('rabbit nacking message', { deliveryTag: msg.fields.deliveryTag });\n // eslint-disable-next-line @typescript-eslint/await-thenable\n await channel.ack(msg);\n };\n\n async getConnection(connection: ConnectionData, vhost?: string): Promise<AmqpConnectionManager> {\n const {\n amqpConnection: connectionLocal,\n creatingConnection,\n connectionCreatedEventName,\n connectionFailedEventName,\n blockReconnect,\n } = connection;\n\n if (blockReconnect) {\n this.#logger.debug('rabbit: block reconnect');\n // @ts-expect-error we are returning undefined while the function clearly expects a connection.\n return undefined;\n }\n\n if (connectionLocal !== null) {\n if (this.options?.disableReconnect || connectionLocal?.isConnected()) {\n this.#logger.debug('rabbit: connection - is connected');\n return connectionLocal;\n }\n this.#logger.debug('rabbit: connection - reconnecting');\n }\n if (creatingConnection) {\n this.#logger.debug('rabbit: creating connection emi');\n const [event, value] = await Promise.race([connectionCreatedEventName, connectionFailedEventName].map(e => once(this.em, e).then(([result]) => [e, result] as const)));\n if (event === connectionCreatedEventName) {\n return value;\n }\n throw value;\n }\n connection.creatingConnection = true;\n let isResolved = false;\n\n // It is import to use it as a function and not as a variable\n // because of k8s changes the env variables\n // and we want to use the new values\n const findServers = () => {\n const userName = process.env.RABBITMQ_USERNAME || 'guest';\n const password = process.env.RABBITMQ_PASSWORD || 'guest';\n const host = this.options?.rabbitHost || process.env.RABBITMQ_SERVICE_HOST || 'localhost';\n\n // Use provided vhost or fall back to this.vhost (quorum-vhost)\n const vhostPath = vhost ?? this.vhost;\n this.#logger.debug('rabbit: creating connection', { host, userName, HEARTBEAT, vhost: vhostPath });\n return [`amqp://${userName}:${password}@${host}/${vhostPath}?heartbeat=${HEARTBEAT}`];\n };\n\n const defaultUrls = findServers();\n const newConnection: AmqpConnectionManager = connect(defaultUrls, { findServers });\n connection.amqpConnection = newConnection;\n\n const { promise, reject, resolve } = createDeferredPromise<AmqpConnectionManager>();\n newConnection.on('error', (err) => {\n this.#logger.error('rabbit: connection error', { err });\n if (!isResolved) {\n isResolved = true;\n reject(err);\n this.em.emit(connectionFailedEventName, err);\n }\n });\n\n newConnection.on('connectFailed', (err) => {\n // Clear all consumer tags across all vhosts\n for (const tagsMap of this.consumersTagsByVhost.values()) {\n tagsMap.clear();\n }\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 // Clear all consumer tags across all vhosts\n for (const tagsMap of this.consumersTagsByVhost.values()) {\n tagsMap.clear();\n }\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 getConnectionForVhost(\n vhost: string,\n type: 'publish' | 'consume',\n ): Promise<AmqpConnectionManager> {\n const connections = type === 'publish' ? this.publishConnections : this.consumeConnections;\n\n if (!connections.has(vhost)) {\n // Create new connection data for this vhost\n const connectionData: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: `${type}ConnectionCreated-${vhost || 'default'}`,\n connectionFailedEventName: `${type}ConnectionFailed-${vhost || 'default'}`,\n blockReconnect: false,\n };\n connections.set(vhost, connectionData);\n }\n\n const connectionData = connections.get(vhost)!;\n return this.getConnection(connectionData, vhost);\n }\n\n getConnectionDataForVhost(\n vhost: string,\n type: 'publish' | 'consume',\n ): ConnectionData {\n const connections = type === 'publish' ? this.publishConnections : this.consumeConnections;\n\n if (!connections.has(vhost)) {\n // Create new connection data for this vhost\n const connectionData: ConnectionData = {\n amqpConnection: null,\n creatingConnection: false,\n connectionCreatedEventName: `${type}ConnectionCreated-${vhost || 'default'}`,\n connectionFailedEventName: `${type}ConnectionFailed-${vhost || 'default'}`,\n blockReconnect: false,\n };\n connections.set(vhost, connectionData);\n }\n\n return connections.get(vhost)!;\n }\n\n async assertChannelForVhost(vhost: string, force = false): Promise<ChannelWrapper> {\n const existingChannel = this.publishChannels.get(vhost);\n const setupPromise = this.publishChannelSetupPromises.get(vhost);\n\n if (!force && existingChannel) {\n return existingChannel;\n }\n\n if (!force && setupPromise) {\n return setupPromise;\n }\n\n const promise = (async () => {\n const connection = this.getConnectionDataForVhost(vhost, 'publish');\n const channel = await this.getNewChannel({ connection });\n this.publishChannels.set(vhost, channel);\n this.publishChannelSetupPromises.set(vhost, null);\n return channel;\n })();\n\n this.publishChannelSetupPromises.set(vhost, promise);\n return promise;\n }\n\n async getNewChannel({\n name = rand().toString(),\n onClose = null,\n options = {},\n connection,\n }: newChannelOpts): Promise<ChannelWrapper> {\n let localConnection!: AmqpConnectionManager;\n try {\n localConnection = await this.getConnection(connection);\n } catch (e) {\n this.#logger.error(`rabbit: error on get connection for new channel ${name} `, { e });\n throw e;\n }\n const channel = localConnection?.createChannel({ ...options });\n 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 assertExchange(exchangeName: string, vhost = ''): Promise<Replies.AssertExchange> {\n const channel: ChannelWrapper = await this.assertChannelForVhost(vhost);\n\n // Get or create vhost-specific exchange cache\n if (!this.exchangesByVhost.has(vhost)) {\n this.exchangesByVhost.set(vhost, {});\n }\n const exchanges = this.exchangesByVhost.get(vhost)!;\n\n if (exchanges[exchangeName]) {\n // Get or create vhost-specific promises\n if (!this.assertExchangePromisesByVhost.has(vhost)) {\n this.assertExchangePromisesByVhost.set(vhost, {});\n }\n const promises = this.assertExchangePromisesByVhost.get(vhost)!;\n delete promises[exchangeName];\n return exchanges[exchangeName];\n }\n\n // Get or create vhost-specific promises\n if (!this.assertExchangePromisesByVhost.has(vhost)) {\n this.assertExchangePromisesByVhost.set(vhost, {});\n }\n const promises = this.assertExchangePromisesByVhost.get(vhost)!;\n\n if (promises[exchangeName]) {\n return promises[exchangeName];\n }\n\n promises[exchangeName] = assertExchangeFanout(channel, exchangeName);\n exchanges[exchangeName] = await promises[exchangeName];\n return exchanges[exchangeName];\n }\n\n async getQueueLength(queue: string): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queue);\n const vhost = this.getVhostForQueue(queue);\n const channel = this.publishChannels.get(vhost);\n if (!channel) {\n throw new RabbitError('channel is not defined');\n }\n const connectionData = this.getConnectionDataForVhost(vhost, 'publish');\n this.#logger.debug('rabbit: getting queue length', { queue, connected: connectionData.amqpConnection?.isConnected() });\n return channel.checkQueue(queue);\n }\n\n private async deleteQueue(queue: string): Promise<Replies.DeleteQueue> {\n RabbitMq.validateName('queue', queue);\n const vhost = this.getVhostForQueue(queue);\n const channel: ChannelWrapper = await this.assertChannelForVhost(vhost);\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 vhost = this.getVhostForQueue(queue);\n const channel: ChannelWrapper = await this.assertChannelForVhost(vhost);\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, vhost?: string): Promise<Replies.AssertQueue> {\n let queue: Replies.AssertQueue;\n // Determine vhost if not provided\n const queueVhost = vhost ?? this.getVhostForQueue(queueName);\n\n const isQuorum = this.isQuorumQueue(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': isQuorum ? 'quorum' : 'classic',\n },\n };\n try {\n const channel: ChannelWrapper = await this.assertChannelForVhost(queueVhost);\n this.#logger.debug('assertQueue->channel.addSetup', { queueName, vhost: queueVhost, queueType: isQuorum ? 'quorum' : 'classic' });\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.assertChannelForVhost(queueVhost, true);\n await this.deleteQueue(queueName);\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 // Store in vhost-specific cache\n if (!this.queuesByVhost.has(queueVhost)) {\n this.queuesByVhost.set(queueVhost, {});\n }\n const queues = this.queuesByVhost.get(queueVhost)!;\n queues[queueName] = queue;\n return queue;\n }\n\n async assertQueue(queueName: string, options?: Options.AssertQueue): Promise<Replies.AssertQueue> {\n RabbitMq.validateName('queue', queueName);\n const vhost = this.getVhostForQueue(queueName);\n\n // Get or create vhost-specific queue cache\n if (!this.queuesByVhost.has(vhost)) {\n this.queuesByVhost.set(vhost, {});\n }\n const queues = this.queuesByVhost.get(vhost)!;\n\n if (queues[queueName]) {\n // Get or create vhost-specific setup promises\n if (!this.queueSetupPromisesByVhost.has(vhost)) {\n this.queueSetupPromisesByVhost.set(vhost, {});\n }\n const setupPromises = this.queueSetupPromisesByVhost.get(vhost)!;\n delete setupPromises[queueName];\n return queues[queueName];\n }\n\n // Get or create vhost-specific setup promises\n if (!this.queueSetupPromisesByVhost.has(vhost)) {\n this.queueSetupPromisesByVhost.set(vhost, {});\n }\n const setupPromises = this.queueSetupPromisesByVhost.get(vhost)!;\n setupPromises[queueName] ??= this.setupQueue(queueName, options, vhost);\n return setupPromises[queueName];\n }\n\n private saveConsumer(queue: string, callback: CallbackFunction, options: ConsumeOptions | undefined, vhost: string): void {\n // Get or create vhost-specific consumers array\n if (!this.consumersToRegisterByVhost.has(vhost)) {\n this.consumersToRegisterByVhost.set(vhost, []);\n }\n const consumers = this.consumersToRegisterByVhost.get(vhost)!;\n\n const isConsumerExist: boolean = consumers.some(consumer => consumer.queue === queue);\n if (!isConsumerExist) {\n this.#logger.info(`rabbit: consumer: ${queue} saved in consumer array for vhost: ${vhost || 'default'}`);\n consumers.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 vhost = this.getVhostForQueue(queue);\n\n // Save consumer for vhost-aware tracking\n this.saveConsumer(queue, callback, options, vhost);\n\n if (vhost === 'quorum-vhost') {\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n }\n\n await this.consumeFromRabbit(queue, callback, options, vhost);\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 | undefined, vhost: string): 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 // Get connection for the appropriate vhost\n const connectionData = this.getConnectionDataForVhost(vhost, 'consume');\n const channel = await this.getNewChannel({ connection: connectionData });\n return channel.addSetup(async (confirmChannel: ConfirmChannel) => {\n await this.assertQueue(queue, optionsWithDefaults);\n await confirmChannel.prefetch(limit!, false);\n const { consumerTag } = await confirmChannel.consume(\n queue,\n async (msg: ConsumeMessageOrNull) => {\n if (!msg) {\n return null;\n }\n\n const {\n [TRACING_HEADER]: traceId, [USER_TRACING_HEADER]: userId, [AUTOMATION_ID_HEADER]: automationId, [CONTEXTS_IDS_HEADER]: userContextIds,\n } = msg.properties.headers ?? {};\n const parsedMessage = RabbitMq.parseMsg(msg);\n const releaseLock = await this.lockRedisIfNeeded(parsedMessage, optionsWithDefaults);\n const trace = newTrace(traceTypes.RABBIT);\n // enableRabbitTrace is a flag to protect from different flows that doesn't work with permission\n // and we don't want to fail the flow because of it\n if (userId && enableRabbitTrace) {\n try {\n await createOrSetRabbitTrace(trace, userId, userContextIds);\n } catch (e) {\n this.#logger.error('rabbit: failed to setRabbitTrace', { userId, e });\n return this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg);\n }\n }\n\n if (traceId) {\n trace.context?.set(TRACING_HEADER, traceId);\n }\n\n if (auditContext) {\n await auditContext(queue, {\n userId,\n automationId,\n });\n }\n const shouldConsume = await this.shouldConsumeMessageByTimestamp(parsedMessage);\n if (!shouldConsume) {\n await this.unlockRedisIfNeeded(releaseLock);\n return this.ack(confirmChannel, msg)(msg);\n }\n\n let messageAcked = false;\n // setting the localAck function to be used in the callback\n\n const localAck = async () => {\n if (messageAcked) {\n return;\n }\n messageAcked = true;\n await this.ack(confirmChannel, msg, true, releaseLock)(msg);\n };\n\n const localNack = async (_: ConsumeMessageOrNull, nackOptions: NackOptions = {}) => {\n if (messageAcked) {\n return;\n }\n this.#logger.debug('rabbit localNack', { messageAcked, uniqueId, deliveryTag: msg.fields.deliveryTag });\n messageAcked = true;\n await this.nack(confirmChannel, queue, optionsWithDefaults, { messageTtl: deadMessageTtl }, msg, releaseLock)(msg, nackOptions);\n };\n\n try {\n return await callback(\n parsedMessage,\n localAck,\n localNack,\n );\n } catch {\n return localNack(msg);\n }\n },\n CONSUMER_DEFAULT_OPTIONS,\n );\n if (!consumerTag) {\n this.#logger.error(`rabbit: failed to consume from queue ${queue}`);\n } else {\n this.#logger.info(`rabbit: adding tag ${consumerTag} to the array for vhost ${vhost || 'default'}.`);\n // Store in vhost-aware consumer tags map\n if (!this.consumersTagsByVhost.has(vhost)) {\n this.consumersTagsByVhost.set(vhost, new Map());\n }\n const tags = this.consumersTagsByVhost.get(vhost)!;\n tags.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 const vhost = this.getVhostForQueue(queue);\n RabbitMq.validateName('exchange', exchange);\n RabbitMq.validateName('queue', queue);\n const { limit } = optionsWithDefaults;\n\n // New vhost-aware implementation\n this.saveConsumer(queue, callback, options, vhost);\n\n if (vhost === 'quorum-vhost') {\n const backoffConfig = getAssertVhostExponentialBackoffConfig();\n await backOff(() => this.assertVHost(), backoffConfig);\n }\n\n const connectionData = this.getConnectionDataForVhost(vhost, 'consume');\n const channel: ChannelWrapper = await this.getNewChannel({\n name: `consume-exchange-${exchange}-queue-${queue}`,\n connection: connectionData,\n });\n\n await channel.addSetup(async (c: ConfirmChannel) => {\n const assertExchange = await assertExchangeFanout(c, exchange);\n await c.assertQueue(queue);\n\n // Store in vhost-aware exchange cache\n if (!this.exchangesByVhost.has(vhost)) {\n this.exchangesByVhost.set(vhost, {});\n }\n const exchanges = this.exchangesByVhost.get(vhost)!;\n exchanges[exchange] = assertExchange;\n\n await c.prefetch(limit!, false);\n await c.bindQueue(queue, exchange, '');\n });\n\n // Actually consume from the queue\n await this.consume(queue, callback, options);\n }\n\n // Used by the microservices to publish messages to the exchange\n async publish(exchange: string, content: any, customHeaders?: PublishOptions['headers'], _isQuorumQueue = true): Promise<void> {\n await setImmediate();\n\n // For exchanges, default to empty vhost (classic) since we don't have queue name context\n // Future enhancement: track exchange-to-vhost mapping based on queue bindings\n const vhost = '';\n\n RabbitMq.validateName('exchange', exchange);\n const channel: ChannelWrapper = await this.assertChannelForVhost(vhost);\n await this.assertExchange(exchange, vhost);\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 async sendToQueue(\n queue: string,\n content: any,\n options?: Options.AssertQueue,\n customHeaders?: PublishOptions['headers'],\n _isQuorumQueue = true, // Deprecated parameter, kept for backwards compatibility\n ): Promise<boolean | undefined> {\n const vhost = this.getVhostForQueue(queue);\n\n try {\n if (vhost === 'quorum-vhost') {\n await this.assertVHost();\n }\n await this.assertChannelForVhost(vhost);\n } catch (e) {\n this.#logger.error(`rabbit sendToQueue: failed to 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 channel = this.publishChannels.get(vhost);\n const res = await channel?.sendToQueue(queue, Buffer.from(JSON.stringify(content)), RabbitMq.getPublishOptions(customHeaders));\n this.#logger.debug(`rabbit: sending to queue ${queue} on vhost ${vhost || 'default'}`, { 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 // TODO: [QUORUM-PHASE-3] Old implementation code will be removed in cleanup phase\n }\n\n async isConnected(): Promise<boolean> {\n if (this.gracefulShutdownStarted) {\n return false;\n }\n\n try {\n this.#logger.debug('rabbit: checking connection status');\n\n // Get all connections from both maps\n const allConnections = [\n ...this.publishConnections.values(),\n ...this.consumeConnections.values(),\n ];\n\n if (allConnections.length === 0) {\n this.#logger.debug('rabbit: no connections established yet');\n return true; // No connections created yet, considered connected\n }\n\n // Check all connections are established\n const connections = await Promise.all(\n allConnections.map(cd => this.getConnection(cd)),\n );\n\n const allConnectionsActive = connections.every(conn => conn.isConnected());\n if (!allConnectionsActive) {\n this.#logger.error('rabbit: isConnected - some connections are not active');\n return false;\n }\n\n // Check all consumers are registered\n for (const [vhost, consumers] of this.consumersToRegisterByVhost) {\n const tags = this.consumersTagsByVhost.get(vhost);\n const unRegisteredConsumers = consumers.filter(c => !tags?.get(c.queue));\n\n if (unRegisteredConsumers.length > 0) {\n const queueNames = unRegisteredConsumers.map(c => c.queue);\n this.#logger.error('rabbit: found unregistered consumers for queues', {\n vhost: vhost || 'default',\n count: queueNames.length,\n queues: queueNames,\n });\n return false;\n }\n\n // Check queue health for this vhost\n const channel = await this.assertChannelForVhost(vhost);\n await channel.waitForConnect();\n await Promise.all(\n consumers.map(c => channel.checkQueue(c.queue)),\n );\n }\n\n this.#logger.debug('rabbit: all connections and consumers are healthy');\n return true;\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 check below\n // During transition, also check old infrastructure\n // isConnected = await this.isConnectedOld();\n }\n\n async gracefulShutdown(signal: string): Promise<void> {\n this.gracefulShutdownStarted = true;\n\n // Count all consumers across all vhosts\n let totalConsumers = 0;\n for (const tags of this.consumersTagsByVhost.values()) {\n totalConsumers += tags.size;\n }\n\n this.#logger.info(`rabbit: [gracefully-shutdown] received ${signal}! canceling #${totalConsumers} consumers across ${this.consumersTagsByVhost.size} vhosts...`);\n\n // Cancel all consumers across all vhosts\n const cancelPromises: Promise<unknown>[] = [];\n for (const [vhost, tagsMap] of this.consumersTagsByVhost) {\n for (const [queue, { channel, consumerTag }] of tagsMap) {\n this.#logger.debug(`rabbit: [gracefully-shutdown] canceling consumer ${consumerTag} for queue ${queue} on vhost ${vhost || 'default'}`);\n cancelPromises.push(channel.cancel(consumerTag));\n }\n // Clear the tags for this vhost\n tagsMap.clear();\n }\n\n // Wait for all cancellations\n const results = await Promise.allSettled(cancelPromises);\n const rejected = results.filter(p => p.status === 'rejected');\n\n if (rejected.length > 0) {\n this.#logger.warn(`rabbit: [gracefully-shutdown] #${rejected.length}/${cancelPromises.length} consumers failed to cancel`);\n } else {\n this.#logger.info('rabbit: [gracefully-shutdown] all consumers successfully canceled.');\n }\n\n // Close all connections\n const allConnections = [\n ...this.publishConnections.values(),\n ...this.consumeConnections.values(),\n ];\n\n await Promise.all(\n allConnections\n .map(cd => cd.amqpConnection?.close())\n .filter((p): p is Promise<void> => p !== undefined),\n );\n\n this.#logger.info('rabbit: [gracefully-shutdown] all connections closed.');\n }\n\n private maskURL = (url: string): string => {\n try {\n const urlObj = new URL(url);\n urlObj.username = '***';\n urlObj.password = '***';\n return urlObj.toString();\n } catch {\n return url;\n }\n };\n}\n\nexport default RabbitMq;\n\nexport {\n sendCeleryTaskViaHttp,\n} from './lib/celery';\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { n as IAfRabbitMq } from "../index-BSNGP44W.cjs";
1
+ import { n as IAfRabbitMq } from "../index-CBlhQYQ_.cjs";
2
2
  import "jest";
3
3
 
4
4
  //#region src/mock/index.d.ts
@@ -1,4 +1,4 @@
1
- import { n as IAfRabbitMq } from "../index-Di_b_UEl.js";
1
+ import { n as IAfRabbitMq } from "../index-CdC0BR3j.js";
2
2
  import "jest";
3
3
 
4
4
  //#region src/mock/index.d.ts
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,`__esModule`,{value:!0});const e=require(`../index.cjs`);let t=require(`vitest`);var n=class{constructor(){this.ack=t.vi.fn(),this.nack=t.vi.fn(),this.assertChannel=t.vi.fn(),this.assertExchange=t.vi.fn(),this.assertQueue=t.vi.fn(),this.consume=t.vi.fn(),this.consumeFromExchange=t.vi.fn(),this.publish=t.vi.fn(),this.sendToQueue=t.vi.fn()}},r=n;exports.default=r;
1
+ Object.defineProperty(exports,`__esModule`,{value:!0});const e=require(`../index.cjs`);let t=require(`vitest`);var n=class{constructor(){this.ack=t.vi.fn(),this.nack=t.vi.fn(),this.assertExchange=t.vi.fn(),this.assertQueue=t.vi.fn(),this.consume=t.vi.fn(),this.consumeFromExchange=t.vi.fn(),this.publish=t.vi.fn(),this.sendToQueue=t.vi.fn()}},r=n;exports.default=r;
2
2
  //# sourceMappingURL=vitest.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.cjs","names":["vi"],"sources":["../../src/mock/vitest.ts"],"sourcesContent":["import { vi, type Mock } from 'vitest';\nimport type { IAfRabbitMq } from '../index';\n\nclass RabbitMq implements IAfRabbitMq {\n ack: Mock<IAfRabbitMq['ack']> = vi.fn();\n\n nack: Mock<IAfRabbitMq['nack']> = vi.fn();\n\n assertChannel: Mock<IAfRabbitMq['assertChannel']> = vi.fn();\n\n assertExchange: Mock<IAfRabbitMq['assertExchange']> = vi.fn();\n\n assertQueue: Mock<IAfRabbitMq['assertQueue']> = vi.fn();\n\n consume: Mock<IAfRabbitMq['consume']> = vi.fn();\n\n consumeFromExchange: Mock<IAfRabbitMq['consumeFromExchange']> = vi.fn();\n\n publish: Mock<IAfRabbitMq['publish']> = vi.fn();\n\n sendToQueue: Mock<IAfRabbitMq['sendToQueue']> = vi.fn();\n}\n\nexport default RabbitMq;\n"],"mappings":"+GAGA,IAAM,EAAN,KAAsC,wBACJA,EAAAA,GAAG,IAAI,WAELA,EAAAA,GAAG,IAAI,oBAEWA,EAAAA,GAAG,IAAI,qBAELA,EAAAA,GAAG,IAAI,kBAEbA,EAAAA,GAAG,IAAI,cAEfA,EAAAA,GAAG,IAAI,0BAEiBA,EAAAA,GAAG,IAAI,cAE/BA,EAAAA,GAAG,IAAI,kBAECA,EAAAA,GAAG,IAAI,GAGzD,EAAe"}
1
+ {"version":3,"file":"vitest.cjs","names":["vi"],"sources":["../../src/mock/vitest.ts"],"sourcesContent":["import { vi, type Mock } from 'vitest';\nimport type { IAfRabbitMq } from '../index';\n\nclass RabbitMq implements IAfRabbitMq {\n ack: Mock<IAfRabbitMq['ack']> = vi.fn();\n\n nack: Mock<IAfRabbitMq['nack']> = vi.fn();\n\n assertExchange: Mock<IAfRabbitMq['assertExchange']> = vi.fn();\n\n assertQueue: Mock<IAfRabbitMq['assertQueue']> = vi.fn();\n\n consume: Mock<IAfRabbitMq['consume']> = vi.fn();\n\n consumeFromExchange: Mock<IAfRabbitMq['consumeFromExchange']> = vi.fn();\n\n publish: Mock<IAfRabbitMq['publish']> = vi.fn();\n\n sendToQueue: Mock<IAfRabbitMq['sendToQueue']> = vi.fn();\n}\n\nexport default RabbitMq;\n"],"mappings":"+GAGA,IAAM,EAAN,KAAsC,wBACJA,EAAAA,GAAG,IAAI,WAELA,EAAAA,GAAG,IAAI,qBAEaA,EAAAA,GAAG,IAAI,kBAEbA,EAAAA,GAAG,IAAI,cAEfA,EAAAA,GAAG,IAAI,0BAEiBA,EAAAA,GAAG,IAAI,cAE/BA,EAAAA,GAAG,IAAI,kBAECA,EAAAA,GAAG,IAAI,GAGzD,EAAe"}
@@ -1,11 +1,10 @@
1
- import { n as IAfRabbitMq } from "../index-BSNGP44W.cjs";
1
+ import { n as IAfRabbitMq } from "../index-CBlhQYQ_.cjs";
2
2
  import { Mock } from "vitest";
3
3
 
4
4
  //#region src/mock/vitest.d.ts
5
5
  declare class RabbitMq implements IAfRabbitMq {
6
6
  ack: Mock<IAfRabbitMq["ack"]>;
7
7
  nack: Mock<IAfRabbitMq["nack"]>;
8
- assertChannel: Mock<IAfRabbitMq["assertChannel"]>;
9
8
  assertExchange: Mock<IAfRabbitMq["assertExchange"]>;
10
9
  assertQueue: Mock<IAfRabbitMq["assertQueue"]>;
11
10
  consume: Mock<IAfRabbitMq["consume"]>;
@@ -1,11 +1,10 @@
1
- import { n as IAfRabbitMq } from "../index-Di_b_UEl.js";
1
+ import { n as IAfRabbitMq } from "../index-CdC0BR3j.js";
2
2
  import { Mock } from "vitest";
3
3
 
4
4
  //#region src/mock/vitest.d.ts
5
5
  declare class RabbitMq implements IAfRabbitMq {
6
6
  ack: Mock<IAfRabbitMq["ack"]>;
7
7
  nack: Mock<IAfRabbitMq["nack"]>;
8
- assertChannel: Mock<IAfRabbitMq["assertChannel"]>;
9
8
  assertExchange: Mock<IAfRabbitMq["assertExchange"]>;
10
9
  assertQueue: Mock<IAfRabbitMq["assertQueue"]>;
11
10
  consume: Mock<IAfRabbitMq["consume"]>;
@@ -1,2 +1,2 @@
1
- import{vi as e}from"vitest";var t=class{constructor(){this.ack=e.fn(),this.nack=e.fn(),this.assertChannel=e.fn(),this.assertExchange=e.fn(),this.assertQueue=e.fn(),this.consume=e.fn(),this.consumeFromExchange=e.fn(),this.publish=e.fn(),this.sendToQueue=e.fn()}};export{t as default};
1
+ import{vi as e}from"vitest";var t=class{constructor(){this.ack=e.fn(),this.nack=e.fn(),this.assertExchange=e.fn(),this.assertQueue=e.fn(),this.consume=e.fn(),this.consumeFromExchange=e.fn(),this.publish=e.fn(),this.sendToQueue=e.fn()}};export{t as default};
2
2
  //# sourceMappingURL=vitest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vitest.js","names":[],"sources":["../../src/mock/vitest.ts"],"sourcesContent":["import { vi, type Mock } from 'vitest';\nimport type { IAfRabbitMq } from '../index';\n\nclass RabbitMq implements IAfRabbitMq {\n ack: Mock<IAfRabbitMq['ack']> = vi.fn();\n\n nack: Mock<IAfRabbitMq['nack']> = vi.fn();\n\n assertChannel: Mock<IAfRabbitMq['assertChannel']> = vi.fn();\n\n assertExchange: Mock<IAfRabbitMq['assertExchange']> = vi.fn();\n\n assertQueue: Mock<IAfRabbitMq['assertQueue']> = vi.fn();\n\n consume: Mock<IAfRabbitMq['consume']> = vi.fn();\n\n consumeFromExchange: Mock<IAfRabbitMq['consumeFromExchange']> = vi.fn();\n\n publish: Mock<IAfRabbitMq['publish']> = vi.fn();\n\n sendToQueue: Mock<IAfRabbitMq['sendToQueue']> = vi.fn();\n}\n\nexport default RabbitMq;\n"],"mappings":"4BAuBA,IAAA,EApBA,KAAsC,wBACJ,EAAG,IAAI,WAEL,EAAG,IAAI,oBAEW,EAAG,IAAI,qBAEL,EAAG,IAAI,kBAEb,EAAG,IAAI,cAEf,EAAG,IAAI,0BAEiB,EAAG,IAAI,cAE/B,EAAG,IAAI,kBAEC,EAAG,IAAI"}
1
+ {"version":3,"file":"vitest.js","names":[],"sources":["../../src/mock/vitest.ts"],"sourcesContent":["import { vi, type Mock } from 'vitest';\nimport type { IAfRabbitMq } from '../index';\n\nclass RabbitMq implements IAfRabbitMq {\n ack: Mock<IAfRabbitMq['ack']> = vi.fn();\n\n nack: Mock<IAfRabbitMq['nack']> = vi.fn();\n\n assertExchange: Mock<IAfRabbitMq['assertExchange']> = vi.fn();\n\n assertQueue: Mock<IAfRabbitMq['assertQueue']> = vi.fn();\n\n consume: Mock<IAfRabbitMq['consume']> = vi.fn();\n\n consumeFromExchange: Mock<IAfRabbitMq['consumeFromExchange']> = vi.fn();\n\n publish: Mock<IAfRabbitMq['publish']> = vi.fn();\n\n sendToQueue: Mock<IAfRabbitMq['sendToQueue']> = vi.fn();\n}\n\nexport default RabbitMq;\n"],"mappings":"4BAqBA,IAAA,EAlBA,KAAsC,wBACJ,EAAG,IAAI,WAEL,EAAG,IAAI,qBAEa,EAAG,IAAI,kBAEb,EAAG,IAAI,cAEf,EAAG,IAAI,0BAEiB,EAAG,IAAI,cAE/B,EAAG,IAAI,kBAEC,EAAG,IAAI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/rabbit",
3
- "version": "5.0.27",
3
+ "version": "5.1.0-alpha.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -75,8 +75,8 @@
75
75
  "@types/node": "^20.14.11",
76
76
  "node-tcp-proxy": "^0.0.28",
77
77
  "ts-node": "^10.9.2",
78
- "@autofleet/logger": "^4.2.45",
79
- "@autofleet/zehut": "^4.7.5"
78
+ "@autofleet/logger": "^4.2.44",
79
+ "@autofleet/zehut": "^4.7.4"
80
80
  },
81
81
  "author": "",
82
82
  "license": "Proprietary",