import { Inject, Injectable, Logger, type OnModuleInit, type OnModuleDestroy, } from '@nestjs/common'; import { SummarizationService } from './summarization.service.js'; import { QueueService, QUEUE_GC, QUEUE_SUMMARIZATION, QUEUE_TIER_MANAGEMENT, } from '../queue/queue.service.js'; import type { Worker } from 'bullmq'; import type { MosaicJobData } from '../queue/queue.service.js'; @Injectable() export class CronService implements OnModuleInit, OnModuleDestroy { private readonly logger = new Logger(CronService.name); private readonly registeredWorkers: Worker[] = []; constructor( @Inject(SummarizationService) private readonly summarization: SummarizationService, @Inject(QueueService) private readonly queueService: QueueService, ) {} async onModuleInit(): Promise { const summarizationSchedule = process.env['SUMMARIZATION_CRON'] ?? '0 */6 * * *'; // every 6 hours const tierManagementSchedule = process.env['TIER_MANAGEMENT_CRON'] ?? '0 3 * * *'; // daily at 3am // M6-003: Summarization repeatable job await this.queueService.addRepeatableJob( QUEUE_SUMMARIZATION, 'summarization', {}, summarizationSchedule, ); const summarizationWorker = this.queueService.registerWorker(QUEUE_SUMMARIZATION, async () => { await this.summarization.runSummarization(); }); this.registeredWorkers.push(summarizationWorker); // M6-005: Tier management repeatable job await this.queueService.addRepeatableJob( QUEUE_TIER_MANAGEMENT, 'tier-management', {}, tierManagementSchedule, ); const tierWorker = this.queueService.registerWorker(QUEUE_TIER_MANAGEMENT, async () => { await this.summarization.runTierManagement(); }); this.registeredWorkers.push(tierWorker); // Retire any repeatable global GC schedule created by older deployments. // Session cleanup is now triggered only by an authorized session lifecycle operation. await this.queueService.removeRepeatableJobs(QUEUE_GC, 'session-gc'); this.logger.log( `BullMQ jobs scheduled: summarization="${summarizationSchedule}", tier="${tierManagementSchedule}"`, ); } async onModuleDestroy(): Promise { // Workers are closed by QueueService.onModuleDestroy — nothing extra needed here. this.registeredWorkers.length = 0; this.logger.log('CronService destroyed (workers managed by QueueService)'); } }