diff --git a/apps/edr-passenger-api/src/modules/payments/payment-events.consumer.ts b/apps/edr-passenger-api/src/modules/payments/payment-events.consumer.ts index a80c63468..777a2704b 100644 --- a/apps/edr-passenger-api/src/modules/payments/payment-events.consumer.ts +++ b/apps/edr-passenger-api/src/modules/payments/payment-events.consumer.ts @@ -1,4 +1,5 @@ import { Injectable, Logger } from '@nestjs/common'; +import { ModuleRef } from '@nestjs/core'; import { Nack, RabbitSubscribe } from '@golevelup/nestjs-rabbitmq'; import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator'; import { @@ -18,7 +19,15 @@ const PASSENGER_QUEUE = PAYMENT_QUEUES[PaymentService.PASSENGER]; export class PaymentEventsConsumer { private readonly logger = new Logger(PaymentEventsConsumer.name); - constructor(private readonly paymentsService: PaymentsService) {} + // IMPORTANT: do NOT constructor-inject PaymentsService here. It is a REQUEST/TRANSIENT-scoped + // provider (its scope bubbles up from a scoped dependency), so it has no singleton instance at + // bootstrap. Constructor-injecting it makes THIS consumer scoped too — and golevelup binds the + // @RabbitSubscribe handler to the singleton instance it discovers at bootstrap. With no such + // instance, the subscription still registers but delivered messages are never dispatched to + // handle(): they pile up unacked and the booking never confirms. Injecting only the lightweight + // (singleton) ModuleRef keeps this consumer a clean singleton; PaymentsService is resolved per + // message via resolve() (get() throws for scoped providers). + constructor(private readonly moduleRef: ModuleRef) {} @IsPublic() @RabbitSubscribe({ @@ -37,7 +46,13 @@ export class PaymentEventsConsumer { `RECEIVED ${event.eventType} (${event.eventId}) ref=${event.referenceId} via RabbitMQ`, ); try { - const result = await this.paymentsService.handlePaymentEvent( + // resolve() (not get()) because PaymentsService is scoped — get() throws for scoped providers. + const paymentsService = await this.moduleRef.resolve( + PaymentsService, + undefined, + { strict: false }, + ); + const result = await paymentsService.handlePaymentEvent( event as unknown as PaymentEventDto, ); this.logger.log(