Files
mp-pilates/packages/server/src/scheduler/scheduler.service.ts
2026-04-09 10:24:44 +08:00

72 lines
2.5 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common'
import { Cron } from '@nestjs/schedule'
import { SlotGeneratorService } from '../time-slot/slot-generator.service'
import { FlashSaleService } from '../flash-sale/flash-sale.service'
@Injectable()
export class SchedulerService {
private readonly logger = new Logger(SchedulerService.name)
constructor(
private readonly slotGenerator: SlotGeneratorService,
private readonly flashSaleService: FlashSaleService,
) {}
/** 02:00 daily — generate slots 14 days ahead from week templates */
@Cron('0 2 * * *')
async handleSlotGeneration(): Promise<void> {
try {
const count = await this.slotGenerator.generateSlots(14)
this.logger.log(`[handleSlotGeneration] Created ${count} new time slots`)
} catch (err) {
this.logger.error('[handleSlotGeneration] Failed to generate slots', err)
}
}
/** 02:30 daily — close past OPEN slots */
@Cron('30 2 * * *')
async handleCleanupSlots(): Promise<void> {
try {
const count = await this.slotGenerator.cleanupExpiredSlots()
this.logger.log(`[handleCleanupSlots] Closed ${count} expired slots`)
} catch (err) {
this.logger.error('[handleCleanupSlots] Failed to clean up slots', err)
}
}
/** 03:00 daily — expire memberships past their end date or with 0 sessions */
@Cron('0 3 * * *')
async handleCheckMemberships(): Promise<void> {
try {
const count = await this.slotGenerator.checkExpiredMemberships()
this.logger.log(`[handleCheckMemberships] Updated ${count} memberships`)
} catch (err) {
this.logger.error('[handleCheckMemberships] Failed to check memberships', err)
}
}
/** 22:00 daily — mark past CONFIRMED bookings as COMPLETED */
@Cron('0 22 * * *')
async handleCompleteBookings(): Promise<void> {
try {
const count = await this.slotGenerator.completeBookings()
this.logger.log(`[handleCompleteBookings] Completed ${count} bookings`)
} catch (err) {
this.logger.error('[handleCompleteBookings] Failed to complete bookings', err)
}
}
/** Every 5 min — expire unpaid flash sale reservations older than 15min */
@Cron('*/5 * * * *')
async handleExpireFlashSaleReservations(): Promise<void> {
try {
const count = await this.flashSaleService.expireUnpaidReservations(15)
if (count > 0) {
this.logger.log(`[handleExpireFlashSaleReservations] Expired ${count} unpaid reservations`)
}
} catch (err) {
this.logger.error('[handleExpireFlashSaleReservations] Failed', err)
}
}
}