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: Array> = []; constructor( @Inject(SummarizationService) private readonly summarization: SummarizationService, @Inject(QueueService) private readonly queueService: QueueService, ) {} async onModuleInit(): Promise { // Local tier deliberately has no BullMQ consumers or repeatable jobs. if (!this.queueService.isEnabled()) { this.logger.log('CronService: BullMQ disabled on local tier — no jobs will be scheduled'); return; } 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(); }); if (summarizationWorker) 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(); }); if (tierWorker) 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)'); } }