All files / apps/notifications-service/src/notifications messaging-resilience.ts

100% Statements 11/11
100% Branches 0/0
100% Functions 3/3
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41  4x   4x 4x   7x 4x                           4x 2x                                    
import { RabbitMQQueueConfig } from '@golevelup/nestjs-rabbitmq';
import { EXCHANGES } from '@app/contracts';
 
export const RETRY_DELAY_MS = 5_000;
export const MAX_ATTEMPTS = 3;
 
export const retryQueue = (queue: string): string => `${queue}.retry`;
export const deadLetterQueue = (queue: string): string => `${queue}.dlq`;
 
/**
 * Retry topology for one consumer queue, using the classic TTL pattern:
 *
 *   main queue --handler fails--> <queue>.retry (no consumer, TTL 5s)
 *        ^                              |
 *        └── x-dead-letter back to ─────┘
 *
 * The retry queue has no consumers; messages sit there until the TTL expires,
 * then RabbitMQ dead-letters them through the default exchange straight back
 * to the main queue (routing key = queue name). After MAX_ATTEMPTS the message
 * is parked in <queue>.dlq for inspection and manual replay.
 */
export function resilienceQueues(queue: string): RabbitMQQueueConfig[] {
  return [
    {
      name: retryQueue(queue),
      options: {
        durable: true,
        messageTtl: RETRY_DELAY_MS,
        deadLetterExchange: '',
        deadLetterRoutingKey: queue,
      },
    },
    {
      name: deadLetterQueue(queue),
      exchange: EXCHANGES.DEAD_LETTER,
      routingKey: queue,
      options: { durable: true },
    },
  ];
}