import type { AsyncUseCase } from '@core/shared/application'; import type { Logger } from '@core/shared/application'; import type { IRaceEventRepository } from '../../domain/repositories/IRaceEventRepository'; import type { IRaceRegistrationRepository } from '../../domain/repositories/IRaceRegistrationRepository'; import type { IPenaltyRepository } from '../../domain/repositories/IPenaltyRepository'; import type { DomainEventPublisher } from '@/shared/domain/DomainEvent'; import { RaceEventStewardingClosedEvent } from '../../domain/events/RaceEventStewardingClosed'; import { Result } from '@core/shared/application/Result'; import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode'; import type { CloseRaceEventStewardingCommand } from '../dto/CloseRaceEventStewardingCommand'; import type { RaceEvent } from '../../domain/entities/RaceEvent'; /** * Use Case: CloseRaceEventStewardingUseCase * * Scheduled job that checks for race events with expired stewarding windows * and closes them, triggering final results notifications. * * This would typically be run by a scheduled job (e.g., every 5 minutes) * to automatically close stewarding windows based on league configuration. */ export class CloseRaceEventStewardingUseCase implements AsyncUseCase { constructor( private readonly logger: Logger, private readonly raceEventRepository: IRaceEventRepository, private readonly raceRegistrationRepository: IRaceRegistrationRepository, private readonly penaltyRepository: IPenaltyRepository, private readonly domainEventPublisher: DomainEventPublisher, ) {} // eslint-disable-next-line @typescript-eslint/no-unused-vars async execute(_command: CloseRaceEventStewardingCommand): Promise>> { try { // Find all race events awaiting stewarding that have expired windows const expiredEvents = await this.raceEventRepository.findAwaitingStewardingClose(); for (const raceEvent of expiredEvents) { await this.closeStewardingForRaceEvent(raceEvent); } return Result.ok(undefined); } catch (error) { this.logger.error('Failed to close race event stewarding', error instanceof Error ? error : new Error(String(error))); return Result.err({ code: 'FAILED_TO_CLOSE_STEWARDING' }); } } private async closeStewardingForRaceEvent(raceEvent: RaceEvent): Promise { try { // Close the stewarding window const closedRaceEvent = raceEvent.closeStewarding(); await this.raceEventRepository.update(closedRaceEvent); // Get list of participating drivers const driverIds = await this.getParticipatingDriverIds(raceEvent); // Check if any penalties were applied during stewarding const hadPenaltiesApplied = await this.checkForAppliedPenalties(raceEvent); // Publish domain event to trigger final results notifications const event = new RaceEventStewardingClosedEvent({ raceEventId: raceEvent.id, leagueId: raceEvent.leagueId, seasonId: raceEvent.seasonId, closedAt: new Date(), driverIds, hadPenaltiesApplied, }); await this.domainEventPublisher.publish(event); } catch (error) { this.logger.error(`Failed to close stewarding for race event ${raceEvent.id}`, error instanceof Error ? error : new Error(String(error))); // In production, this would trigger alerts/monitoring throw error; } } private async getParticipatingDriverIds(raceEvent: RaceEvent): Promise { return await this.raceRegistrationRepository.getRegisteredDrivers(raceEvent.id); } private async checkForAppliedPenalties(raceEvent: RaceEvent): Promise { const penalties = await this.penaltyRepository.findByRaceId(raceEvent.id); return penalties.length > 0; } }