Initial commit

This commit is contained in:
siliconsolder committed 2026-09-07 09:54:30 +00:00
commit 38c24fc9dc
166 files changed
+22002

No files matched your search

@@ -0,0 +1,41 @@
import { and, eq, lt } from 'drizzle-orm'
import { db } from '../../db/client.js'
import { notifications, topics } from '../../db/schema.js'
import { resolveRetentionDefaultDays } from '../admin/system-settings.js'
const CLEANUP_INTERVAL_MS = 60 * 60 * 1000 // 1 hour
// Per-topic retentionDays overrides the global default; 0 means "forever".
// See docs/phase1/03-database-model.md, "Retention cleanup".
export async function runRetentionCleanup(): Promise<number> {
const topicRows = await db.select().from(topics)
const retentionDefaultDays = await resolveRetentionDefaultDays()
let totalDeleted = 0
for (const topic of topicRows) {
const retentionDays = topic.retentionDays ?? retentionDefaultDays
if (retentionDays === 0) continue
const cutoff = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000)
const deleted = await db
.delete(notifications)
.where(and(eq(notifications.topicId, topic.id), lt(notifications.createdAt, cutoff)))
.returning({ id: notifications.id })
totalDeleted += deleted.length
}
return totalDeleted
}
export function startRetentionCleanupJob(
onError: (err: unknown) => void = console.error,
): NodeJS.Timeout {
const run = () => {
runRetentionCleanup().catch(onError)
}
run() // catch up on anything overdue from before this boot
const timer = setInterval(run, CLEANUP_INTERVAL_MS)
timer.unref() // never block process shutdown just to keep this alive
return timer
}