mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-27 05:57:16 +00:00
5ba4fb7dc9
Several append-only tables had no purge mechanism and grew unbounded. Add age-based retention to the 2h MaintenanceFunction (and the manual path) via a new CleanupUnboundedTablesAsync orchestrator (per-table try/catch, fixed const windows, mirroring the DistressReports pattern): - GlobalNotifications + TenantNotifications: hybrid retention — dismissed rows pruned 30d after DismissedAt, any row pruned 180d after CreatedAt. Unread (still-actionable) admin warnings survive the dismiss window so they are never silently lost; the 180d catch-all bounds the table. Shared pure predicate NotificationRetentionFilter.BuildPredicate (unit-tested). - HardwareRejectionNotificationTracker: 30d (FirstNotifiedAt). Pruning re-arms the lifetime dedup, so a model rejected again >30d later re-bells (intended). - AuditLogs: 180d (system Timestamp, cross-partition). - UsageMetrics: 180d (PartitionKey date-string range). - BackupJobs: 365d (QueuedAtUtc). PlatformStats intentionally excluded — it is a single upserted row, not append-only. Bootstrap sessions left as-is (feature currently unused). Each repo delete mirrors DeleteUserActivityOlderThanAsync: server-side "X lt cutoff" filter + select PK/RK + delete loop. Deletes are resumable across runs, so a partial run self-heals on the next cycle. Observability: end-of-run MaintenanceLongRunning Warning OpsEvent if RunAllAsync exceeds 10min, dual-registered in OpsAlertRulesSection.tsx, to surface a run climbing toward the 60min functionTimeout before a future hard-abort (which emits nothing). Inert until backend redeploy; first post-deploy run bulk-prunes the backlog. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>