SPB Git

Repository Public

janitor.ts 2.1 KB 46 lines typescript

1/**2 * Daily retention (see the comment at the bottom of migrations/001_init.sql):3 *   terminal_events: settings.sessionRetentionDays (default 90) · node_metrics: 14 d ·4 *   login_attempts: 30 d · audit_events: 400 d · notifications: 90 d ·5 *   auth_sessions: 7 d after expiry/revocation · preauth_challenges: once expired6 */7import type { FastifyBaseLogger } from 'fastify';8import type { Db } from './db.js';910export async function runJanitor(db: Db): Promise<Record<string, number>> {11  const del = async (sql: string): Promise<number> => (await db.q(`WITH d AS (${sql} RETURNING 1) SELECT count(*)::int AS n FROM d`))[0]?.n as number;12  return {13    terminal_events: await del(14      `DELETE FROM terminal_events e USING terminal_sessions s15        WHERE s.id = e.session_id AND e.at < now() - make_interval(days => coalesce(16          (SELECT least(greatest((a.settings->>'sessionRetentionDays')::int, 1), 3650) FROM application_settings a17            WHERE a.user_id = s.owner_id AND a.settings->>'sessionRetentionDays' ~ '^[0-9]{1,4}$'), 90))`,18    ),19    node_metrics: await del("DELETE FROM node_metrics WHERE at < now() - interval '14 days'"),20    login_attempts: await del("DELETE FROM login_attempts WHERE at < now() - interval '30 days'"),21    audit_events: await del("DELETE FROM audit_events WHERE at < now() - interval '400 days'"),22    notifications: await del("DELETE FROM notifications WHERE created_at < now() - interval '90 days'"),23    auth_sessions: await del(24      "DELETE FROM auth_sessions WHERE expires_at < now() - interval '7 days' OR revoked_at < now() - interval '7 days'",25    ),26    preauth_challenges: await del('DELETE FROM preauth_challenges WHERE expires_at < now()'),27  };28}2930export function startJanitor(db: Db, log: FastifyBaseLogger): () => void {31  const run = (): void => {32    runJanitor(db).then(33      (deleted) => log.info({ deleted }, 'janitor pass'),34      (err: unknown) => log.error({ err }, 'janitor failed'),35    );36  };37  const first = setTimeout(run, 60_000);38  const timer = setInterval(run, 24 * 3600 * 1000);39  first.unref();40  timer.unref();41  return () => {42    clearTimeout(first);43    clearInterval(timer);44  };45}46
Files main
Menu

Theme