Files
AISHub/src/ais_hub/storage/retention.py
T
2026-05-04 08:13:38 +03:00

65 lines
2.0 KiB
Python

"""Periodic retention cleanup for history tables."""
from __future__ import annotations
import asyncio
import logging
import sqlite3
import time
import aiosqlite
from ..config import StorageCfg
from ..core.stats import Stats
log = logging.getLogger(__name__)
async def run_retention(conn: aiosqlite.Connection, cfg: StorageCfg, stats: Stats) -> None:
"""Background task: periodically delete rows older than retention limits."""
interval = max(60, cfg.retention_interval_sec)
while True:
try:
await asyncio.sleep(interval)
await cleanup_once(conn, cfg, stats)
except asyncio.CancelledError:
raise
except Exception:
log.exception("retention sweep failed")
stats.incr("retention_errors")
async def cleanup_once(conn: aiosqlite.Connection, cfg: StorageCfg, stats: Stats) -> None:
"""Run one retention sweep; caller ensures this is not re-entrant."""
now = time.time()
rows_total = 0
targets = (
("ais_dynamic", cfg.retention.ais_dynamic_days),
("gps_fix", cfg.retention.gps_fix_days),
("raw_nmea", cfg.retention.raw_nmea_days),
("radio_telemetry", cfg.retention.radio_telemetry_days),
)
for table, days in targets:
if days <= 0:
continue
cutoff = now - days * 86400.0
try:
cur = await conn.execute(f"DELETE FROM {table} WHERE ts < ?", (cutoff,))
await conn.commit()
rows_total += cur.rowcount or 0
stats.incr(f"retention_deleted_{table}", cur.rowcount or 0)
except sqlite3.OperationalError as exc:
log.warning("retention: transient error on %s: %s", table, exc)
stats.incr("retention_transient_errors")
except Exception:
log.exception("retention: error deleting from %s", table)
stats.incr("retention_errors")
if rows_total > 0:
log.info("retention sweep removed %d rows", rows_total)
stats.incr("retention_sweeps")
__all__ = ["run_retention", "cleanup_once"]