import { Transport, MicroserviceOptions, RmqOptions } from '@nestjs/microservices'; import * as amqp from 'amqplib'; export const getRabbitMQOptions = (queueName: string, url?: string, pluginId?: string): MicroserviceOptions => { const routingKeys: string[] = ['#']; if (pluginId) { routingKeys.push(`plugin.${pluginId}.*`); } return { transport: Transport.RMQ, options: { urls: [url || process.env.RABBITMQ_URL || 'amqp://localhost:5672'], queue: queueName, exchange: 'system_events', exchangeType: 'topic', routingKey: routingKeys, queueOptions: { durable: true, }, persistent: true, noAck: true, } as RmqOptions['options'] & { routingKey: string[] }, }; }; export const getRabbitMQClientOptions = (url?: string) => { return { transport: Transport.RMQ as const, options: { urls: [url || process.env.RABBITMQ_URL || 'amqp://localhost:5672'], queue: 'core_queue', exchange: 'system_events', exchangeType: 'topic', queueOptions: { durable: true, }, }, }; }; /** * Bind a queue to the system_events exchange with the given routing keys. * NestJS 10's ServerRMQ does not automatically bind queues to exchanges, * so this must be called after app.startAllMicroservices(). * NestJS 11+ handles this automatically via the exchange/routingKey options. */ export async function setupQueueBindings( queueName: string, routingKeys: string[], url?: string, ): Promise { const rmqUrl = url || process.env.RABBITMQ_URL || 'amqp://localhost:5672'; const conn = await amqp.connect(rmqUrl); try { const channel = await conn.createChannel(); await channel.assertExchange('system_events', 'topic', { durable: true }); await channel.assertQueue(queueName, { durable: true }); for (const key of routingKeys) { await channel.bindQueue(queueName, 'system_events', key); } await channel.close(); } finally { await conn.close().catch(() => {}); } }