Files
motovaultpro/backend/src/core/scheduler/index.ts
2025-12-25 10:50:09 -06:00

100 lines
3.1 KiB
TypeScript

/**
* @ai-summary Centralized cron job scheduler
* @ai-context Uses node-cron for scheduling background tasks
*/
import cron from 'node-cron';
import { logger } from '../logging/logger';
import { processScheduledNotifications } from '../../features/notifications/jobs/notification-processor.job';
import { processAccountPurges } from '../../features/user-profile/jobs/account-purge.job';
import {
processScheduledBackups,
setBackupJobPool,
} from '../../features/backup/jobs/backup-scheduled.job';
import {
processBackupRetention,
setBackupCleanupJobPool,
} from '../../features/backup/jobs/backup-cleanup.job';
import { pool } from '../config/database';
let schedulerInitialized = false;
export function initializeScheduler(): void {
if (schedulerInitialized) {
logger.warn('Scheduler already initialized, skipping');
return;
}
logger.info('Initializing cron scheduler');
// Initialize backup job pools
setBackupJobPool(pool);
setBackupCleanupJobPool(pool);
// Daily notification processing at 8 AM
cron.schedule('0 8 * * *', async () => {
logger.info('Running scheduled notification job');
try {
await processScheduledNotifications();
} catch (error) {
logger.error('Scheduled notification job failed', {
error: error instanceof Error ? error.message : String(error)
});
}
});
// Daily account purge job at 2 AM (GDPR compliance - 30-day grace period)
cron.schedule('0 2 * * *', async () => {
logger.info('Running account purge job');
try {
const result = await processAccountPurges();
logger.info('Account purge job completed successfully', {
processed: result.processed,
deleted: result.deleted,
errors: result.errors.length,
});
} catch (error) {
logger.error('Account purge job failed', {
error: error instanceof Error ? error.message : String(error)
});
}
});
// Check for scheduled backups every minute
cron.schedule('* * * * *', async () => {
logger.debug('Checking for scheduled backups');
try {
await processScheduledBackups();
} catch (error) {
logger.error('Scheduled backup check failed', {
error: error instanceof Error ? error.message : String(error)
});
}
});
// Backup retention cleanup at 4 AM daily (after backups complete)
cron.schedule('0 4 * * *', async () => {
logger.info('Running backup retention cleanup job');
try {
const result = await processBackupRetention();
logger.info('Backup retention cleanup completed', {
processed: result.processed,
totalDeleted: result.totalDeleted,
totalFreedBytes: result.totalFreedBytes,
errors: result.errors.length,
});
} catch (error) {
logger.error('Backup retention cleanup failed', {
error: error instanceof Error ? error.message : String(error)
});
}
});
schedulerInitialized = true;
logger.info('Cron scheduler initialized - notification (8 AM), account purge (2 AM), backup check (every min), retention cleanup (4 AM)');
}
export function isSchedulerInitialized(): boolean {
return schedulerInitialized;
}