UNPKG

@goparrot/pubsub-event-bus

Version:
82 lines 4.45 kB
import { __decorate, __metadata, __param } from "tslib"; import { Inject, Injectable } from '@nestjs/common'; import { chain, times } from 'lodash'; import { RetryStrategyEnum } from '../../interface'; import { LoggerProvider } from '../../provider'; import { CQRS_BINDING_QUEUE_CONFIG, CQRS_EXCHANGE_CONFIG, CQRS_RETRY_OPTIONS } from '../../utils/configuration'; import { DEFAULT_DELAY_QUEUE_NAME_PREFIX, DEFAULT_RETRY_DELAY_EXCHANGE_NAME, DEFAULT_RETRY_REQUEUE_EXCHANGE_NAME, ORIGIN_EXCHANGE_HEADER, RETRY_COUNT_HEADER, } from '../../utils/retry-constants'; import { calculateDelay, getMessageExchange } from '../../utils'; let DeadLetterTtlRetryStrategy = class DeadLetterTtlRetryStrategy { constructor(rootRetryOptions, assertExchangeOptions, bindingQueueOptions) { this.rootRetryOptions = rootRetryOptions; this.assertExchangeOptions = assertExchangeOptions; this.bindingQueueOptions = bindingQueueOptions; this.strategy = RetryStrategyEnum.DEAD_LETTER_TTL; } get logger() { return LoggerProvider.logger; } async setupInfrastructure(channelWrapper, wrappersWithRetryStrategy) { const delays = chain(wrappersWithRetryStrategy) .flatMap((wrapper) => { const { delay = this.rootRetryOptions.delay, maxRetryAttempts = this.rootRetryOptions.maxRetryAttempts } = wrapper.options.retryOptions ?? {}; return times(maxRetryAttempts, (retryCount) => calculateDelay(delay, retryCount + 1)); }) .uniq() .value(); await channelWrapper.addSetup(async (channel) => { await Promise.all([ channel .assertExchange(DEFAULT_RETRY_DELAY_EXCHANGE_NAME, 'topic', this.assertExchangeOptions) .then(() => this.logger.log(`Delay auto retry exchange "${DEFAULT_RETRY_DELAY_EXCHANGE_NAME}" asserted`)), channel .assertExchange(DEFAULT_RETRY_REQUEUE_EXCHANGE_NAME, 'topic', this.assertExchangeOptions) .then(() => this.logger.log(`Requeue auto retry exchange "${DEFAULT_RETRY_REQUEUE_EXCHANGE_NAME}" asserted`)), ...delays.map(async (delay) => { const queue = `${DEFAULT_DELAY_QUEUE_NAME_PREFIX}.${delay}`; await channel.assertQueue(queue, { ...this.bindingQueueOptions, messageTtl: delay, deadLetterExchange: DEFAULT_RETRY_REQUEUE_EXCHANGE_NAME, }); await channel.bindQueue(queue, DEFAULT_RETRY_DELAY_EXCHANGE_NAME, `#.retry.${delay}`); this.logger.log(`Delay queue asserted "${queue}" asserted`); }), ...wrappersWithRetryStrategy.map(async (handlerWrapper) => { const { queue } = handlerWrapper; await channel.bindQueue(queue, DEFAULT_RETRY_REQUEUE_EXCHANGE_NAME, `${queue}.#`); }), ]); }); } async requeue(channelWrapper, handlerWrapper, event) { const { queue, handler, options: { retryOptions }, } = handlerWrapper; const message = event.message(); if (!message) { return; } const { delay = this.rootRetryOptions.delay } = retryOptions ?? {}; const retryCount = event.retryCount + 1; const delayValue = calculateDelay(delay, retryCount); const routingKey = `${queue}.retry.${delayValue}`; await channelWrapper.publish(DEFAULT_RETRY_DELAY_EXCHANGE_NAME, routingKey, event.payload, { ...message.properties, type: message.properties.type, headers: { ...message.properties.headers, [RETRY_COUNT_HEADER]: retryCount, [ORIGIN_EXCHANGE_HEADER]: getMessageExchange(message), }, }); this.logger.log(`Event ${event.constructor.name} was republished to "${queue}" queue with ${delayValue} ms delay`, handler.name); } }; DeadLetterTtlRetryStrategy = __decorate([ Injectable(), __param(0, Inject(CQRS_RETRY_OPTIONS)), __param(1, Inject(CQRS_EXCHANGE_CONFIG)), __param(2, Inject(CQRS_BINDING_QUEUE_CONFIG)), __metadata("design:paramtypes", [Object, Object, Object]) ], DeadLetterTtlRetryStrategy); export { DeadLetterTtlRetryStrategy }; //# sourceMappingURL=DeadLetterTtlRetryStrategy.js.map