freellmapi / server /src /services /request-retention.ts
Nryn215's picture
Deploy: Enable and enforce pure ELO-based Intelligence routing strategy
ed57015
Raw
History Blame Contribute Delete
2.03 kB
import { getDb } from '../db/index.js';
const DAY_MS = 24 * 60 * 60 * 1000;
const DEFAULT_RETENTION_DAYS = 90;
const DEFAULT_MAX_ROWS = 100_000;
const PRUNE_INTERVAL_MS = 60_000;
type RetentionDb = ReturnType<typeof getDb>;
export interface RequestAnalyticsRetentionConfig {
retentionDays: number;
maxRows: number;
}
let nextPruneAtMs = 0;
function readNonNegativeInt(name: string, defaultValue: number): number {
const raw = process.env[name];
if (raw === undefined || raw.trim() === '') return defaultValue;
const parsed = Number(raw);
if (!Number.isInteger(parsed) || parsed < 0) return defaultValue;
return parsed;
}
function toSqliteTimestamp(date: Date): string {
return date.toISOString().slice(0, 19).replace('T', ' ');
}
export function getRequestAnalyticsRetentionConfig(): RequestAnalyticsRetentionConfig {
return {
retentionDays: readNonNegativeInt('REQUEST_ANALYTICS_RETENTION_DAYS', DEFAULT_RETENTION_DAYS),
maxRows: readNonNegativeInt('REQUEST_ANALYTICS_MAX_ROWS', DEFAULT_MAX_ROWS),
};
}
export function pruneRequestAnalytics(options: {
db?: RetentionDb;
force?: boolean;
now?: Date;
} = {}): { deleted: number; skipped: boolean } {
const now = options.now ?? new Date();
const nowMs = now.getTime();
if (!options.force && nowMs < nextPruneAtMs) {
return { deleted: 0, skipped: true };
}
nextPruneAtMs = nowMs + PRUNE_INTERVAL_MS;
const db = options.db ?? getDb();
const { retentionDays, maxRows } = getRequestAnalyticsRetentionConfig();
let deleted = 0;
if (retentionDays > 0) {
const cutoff = toSqliteTimestamp(new Date(nowMs - retentionDays * DAY_MS));
deleted += db.prepare('DELETE FROM requests WHERE created_at < ?').run(cutoff).changes;
}
if (maxRows > 0) {
deleted += db.prepare(`
DELETE FROM requests
WHERE id IN (
SELECT id
FROM requests
ORDER BY created_at DESC, id DESC
LIMIT -1 OFFSET ?
)
`).run(maxRows).changes;
}
return { deleted, skipped: false };
}