Files
BanGUI/backend/app/tasks/history_sync.py

68 lines
1.8 KiB
Python

"""History sync background task.
Periodically copies new records from the fail2ban sqlite database into the
BanGUI application archive table to prevent gaps when fail2ban purges old rows.
"""
from __future__ import annotations
import datetime
from typing import TYPE_CHECKING
import structlog
from app.db import open_db
from app.services import history_service
from app.utils.runtime_state import get_effective_settings
if TYPE_CHECKING:
from fastapi import FastAPI
from app.config import Settings
log: structlog.stdlib.BoundLogger = structlog.get_logger()
#: Stable APScheduler job id.
JOB_ID: str = "history_sync"
#: Interval in seconds between sync runs.
HISTORY_SYNC_INTERVAL: int = 300
#: Backfill window when archive is empty (seconds).
BACKFILL_WINDOW: int = 648000
async def _run_sync_with_settings(settings: Settings) -> None:
socket_path: str = settings.fail2ban_socket
db = await open_db(settings.database_path)
try:
synced = await history_service.sync_from_fail2ban_db(db, socket_path)
log.info("history_sync_complete", synced=synced)
except Exception:
log.exception("history_sync_failed")
finally:
await db.close()
async def _run_sync(app: FastAPI) -> None:
await _run_sync_with_settings(get_effective_settings(app))
def register(app: FastAPI) -> None:
"""Register the history sync periodic job.
Should be called after scheduler startup, from the lifespan handler.
"""
settings = get_effective_settings(app)
app.state.scheduler.add_job(
_run_sync_with_settings,
trigger="interval",
seconds=HISTORY_SYNC_INTERVAL,
kwargs={"settings": settings},
id=JOB_ID,
replace_existing=True,
next_run_time=datetime.datetime.now(tz=datetime.UTC),
)
log.info("history_sync_scheduled", interval_seconds=HISTORY_SYNC_INTERVAL)