Files
uptime-monitoring/src/worker/scheduled/cleanup.ts
T

46 lines
2.2 KiB
TypeScript

import { lt } from 'drizzle-orm';
import { getDb } from '../db/client';
import { aiEvents, checks, loginAttempts, monitorDailyStats, notificationDeliveries, sessions } from '../db/schema';
const LOGIN_ATTEMPT_RETENTION_MS = 60 * 60 * 1000;
const CHECK_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
const DAILY_STATS_RETENTION_MS = 400 * 24 * 60 * 60 * 1000;
const DELIVERY_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
export const AI_EVENT_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
/**
* Cheap, high-frequency cleanup for the every-5-minute cron. Only touches the auth tables,
* which stay tiny and are indexed on the column filtered here, so each delete is a bounded
* range scan. Security-sensitive (session expiry, login rate limiting) so it must stay fresh.
*/
export async function cleanupExpiredAuthRecords(env: Env) {
const db = getDb(env);
const now = new Date();
await db.batch([
db.delete(sessions).where(lt(sessions.expiresAt, now)),
db.delete(loginAttempts).where(lt(loginAttempts.attemptedAt, new Date(now.getTime() - LOGIN_ATTEMPT_RETENTION_MS))),
]);
}
/**
* Retention pruning for the high-volume tables. Runs once per day from the rollup cron.
*
* At 20 monitors on 5-minute checks the `checks` table alone holds ~40k rows; running these
* deletes every 5 minutes would scan the whole table each time and blow past D1's free-tier
* "rows read" budget (~5M/day). Each column filtered below is backed by a single-column index
* so the delete only scans the expiring slice, and running daily keeps that scan to ~one day
* of rows.
*/
export async function cleanupStaleData(env: Env, now = new Date()) {
const db = getDb(env);
const checkCutoff = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()) - CHECK_RETENTION_MS;
await db.batch([
db.delete(checks).where(lt(checks.checkedAt, new Date(checkCutoff))),
db.delete(monitorDailyStats).where(lt(monitorDailyStats.day, new Date(now.getTime() - DAILY_STATS_RETENTION_MS))),
db.delete(notificationDeliveries).where(lt(notificationDeliveries.createdAt, new Date(now.getTime() - DELIVERY_RETENTION_MS))),
db.delete(aiEvents).where(lt(aiEvents.createdAt, new Date(now.getTime() - AI_EVENT_RETENTION_MS))),
]);
}