Newer
Older
navi-1 / navi / export / loop.py
"""Background rebuild loop for the export snapshot.

Same shape as the other lifespan loops (cleanup, recall, pending sweep): one
task, never allowed to die, logging and retrying on the next tick. The first
build happens at startup, so a restart is also a refresh.
"""

import asyncio

import structlog

from navi.config import settings
from navi.export.builder import build_export

log = structlog.get_logger()

_MIN_INTERVAL_SECONDS = 15 * 60


def export_interval_seconds() -> float:
    return max(_MIN_INTERVAL_SECONDS, settings.navi_export_interval_hours * 3600)


async def export_loop(store) -> None:
    """Rebuild the snapshot every `navi_export_interval_hours`."""
    interval = export_interval_seconds()
    while True:
        try:
            pool = await store._get_pool()
            await build_export(pool)
        except asyncio.CancelledError:
            raise
        except Exception:
            # A failed build leaves the previous file and manifest in place:
            # built_at keeps telling the truth, and the consumer sees the
            # snapshot getting older instead of silently stale-new.
            log.exception("export.build_failed")
        await asyncio.sleep(interval)