add features
This commit is contained in:
114
backend/src/jobs/audit-cleanup.job.ts
Normal file
114
backend/src/jobs/audit-cleanup.job.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* Audit Cleanup Job
|
||||
*
|
||||
* Runs the GDPR IP anonymisation task on a schedule.
|
||||
* Must be started once from server.ts during application boot.
|
||||
*
|
||||
* Two scheduling options are shown:
|
||||
* 1. node-cron (recommended) — cron expression, survives DST changes
|
||||
* 2. setInterval (fallback) — simpler, no extra dependency
|
||||
*
|
||||
* Install node-cron if using option 1:
|
||||
* npm install node-cron
|
||||
* npm install --save-dev @types/node-cron
|
||||
*/
|
||||
|
||||
import auditService from '../services/audit.service';
|
||||
import logger from '../utils/logger';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Option 1 (RECOMMENDED): node-cron
|
||||
//
|
||||
// Runs every day at 02:00 local server time.
|
||||
// The cron expression format is: second(optional) minute hour dom month dow
|
||||
//
|
||||
// Uncomment this block and comment out the setInterval block below.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
import cron from 'node-cron';
|
||||
|
||||
let cronJob: cron.ScheduledTask | null = null;
|
||||
|
||||
export function startAuditCleanupJob(): void {
|
||||
if (cronJob) {
|
||||
logger.warn('Audit cleanup job already running — skipping duplicate start');
|
||||
return;
|
||||
}
|
||||
|
||||
// '0 2 * * *' = every day at 02:00
|
||||
cronJob = cron.schedule('0 2 * * *', async () => {
|
||||
logger.info('Audit cleanup job: starting IP anonymisation');
|
||||
await auditService.anonymizeOldIpAddresses();
|
||||
logger.info('Audit cleanup job: IP anonymisation complete');
|
||||
}, {
|
||||
scheduled: true,
|
||||
timezone: 'Europe/Vienna', // Feuerwehr Rems is in Austria
|
||||
});
|
||||
|
||||
logger.info('Audit cleanup job scheduled (node-cron, daily at 02:00 Europe/Vienna)');
|
||||
}
|
||||
|
||||
export function stopAuditCleanupJob(): void {
|
||||
if (cronJob) {
|
||||
cronJob.stop();
|
||||
cronJob = null;
|
||||
logger.info('Audit cleanup job stopped');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Option 2 (FALLBACK): setInterval
|
||||
//
|
||||
// Runs every 24 hours from the moment the server starts.
|
||||
// Simpler — no extra dependency — but does not align to wall-clock time
|
||||
// and will drift if the server restarts frequently.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const INTERVAL_MS = 24 * 60 * 60 * 1000; // 24 hours
|
||||
|
||||
let cleanupInterval: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
export function startAuditCleanupJob(): void {
|
||||
if (cleanupInterval !== null) {
|
||||
logger.warn('Audit cleanup job already running — skipping duplicate start');
|
||||
return;
|
||||
}
|
||||
|
||||
// Run once on startup to catch any backlog, then repeat on schedule.
|
||||
// We intentionally do not await — startup must not be blocked.
|
||||
runAuditCleanup();
|
||||
|
||||
cleanupInterval = setInterval(() => {
|
||||
runAuditCleanup();
|
||||
}, INTERVAL_MS);
|
||||
|
||||
logger.info('Audit cleanup job scheduled (setInterval, 24h interval)');
|
||||
}
|
||||
|
||||
export function stopAuditCleanupJob(): void {
|
||||
if (cleanupInterval !== null) {
|
||||
clearInterval(cleanupInterval);
|
||||
cleanupInterval = null;
|
||||
logger.info('Audit cleanup job stopped');
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Core cleanup function — called by both scheduler options
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export async function runAuditCleanup(): Promise<void> {
|
||||
try {
|
||||
logger.debug('Audit cleanup: running IP anonymisation');
|
||||
await auditService.anonymizeOldIpAddresses();
|
||||
} catch (error) {
|
||||
// anonymizeOldIpAddresses() swallows its own errors, but we add a second
|
||||
// layer of protection here so that a scheduler implementation mistake
|
||||
// cannot crash the process.
|
||||
logger.error('Audit cleanup job: unexpected error', {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user