feat(db): scheduled data-retention pruning for log/snapshot tables - #660
Conversation
Adds a conservative, auto-pruning retention job so high-volume append-only and superseded-snapshot tables don't grow unbounded (precautionary D1 hygiene; the DB isn't at its size limit yet). - src/db/retention.ts: RETENTION_POLICY (webhook_events 30d, audit_events 90d, ai_usage_events 90d, product_usage_events 180d, github_rate_limit_observations 30d, signal_snapshots/score_previews/repo_snapshots 90d) + pruneExpiredRecords, which deletes rows older than each window in bounded rowid batches (cap per table per run). Table/column names come only from the hardcoded policy and are identifier-validated; the cutoff is bound. Current-state/reference tables (repositories, settings, PRs, issues, contributors, repository_ai_keys, etc.) are intentionally NOT pruned. - Wired as a daily (03:00 UTC) prune-retention queue job via the cron; processJob runs it and audits the outcome (retention.prune). - GET /v1/internal/retention/preview: read-only dry-run that reports the rows the next prune would delete, per table (deletes nothing). Tests cover dry-run vs real delete, the batch loop + per-table cap, the identifier guard, the audit, processJob, the preview route, and that protected tables are excluded. Coverage holds above the 97% gate.
|
Note Gittensory Gate skippedPR closed before full evaluation. No late first comment was created.
💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →. Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers. |
|
Superagent didn't find any vulnerabilities or security issues in this PR. |
|
gittensory · advisory review Reviewed 6 changed file(s) — two independent AI reviewers. Suggested action: ✅ Safe to merge — both reviewers found no blocking issues. Reviewer A · Suggestions
Worth double-checking
Reviewer B · Suggestions
Worth double-checking
|
What
A conservative, auto-pruning retention job so high-volume append-only / superseded-snapshot tables don't grow unbounded. Precautionary D1 hygiene (the DB isn't at its size limit yet; the recent overload was load/concurrency, not size).
Policy (
src/db/retention.ts→RETENTION_POLICY)Only append-only logs / usage metrics / superseded snapshots (latest-matters) are pruned. Current-state and reference tables are intentionally excluded —
repositories,repository_settings,pull_requests,issues,contributors,repository_ai_keys, focus manifests, registry/scoring snapshots.How
pruneExpiredRecordsdeletes rows older than each window in boundedrowidbatches (1000/batch, capped at 50k/table/run so a first prune of a backlog can't blow the D1 statement budget; the daily cron drains the rest). Table/column names come only from the hardcoded policy and are identifier-validated (^[a-z_]+$); the cutoff is bound as a parameter.prune-retentionqueue job via the existing cron;processJobruns it and audits the outcome (retention.prune).GET /v1/internal/retention/preview— read-only dry-run that reports the rows the next prune would delete, per table. Deletes nothing. Use it to see what the cron will remove.Safety / reversibility
"CURRENT_TIMESTAMP"in a timestamp column sort after real ISO dates, so they're naturally skipped bycol < cutoff(a bounded, non-growing legacy set).Tests
Dry-run vs real delete, the multi-batch loop + per-table cap, the identifier guard, the audit event,
processJob, the preview route, and an assertion that protected tables are excluded from the policy. Full suite green; coverage holds above the 97% gate.5th and final PR from the gate-hang investigation thread (after #652, #655, #656, #657).