feat: embedded flow-watcher in API lifespan with startup sync
This commit is contained in:
parent
c65e3ed332
commit
338cdcf108
3 changed files with 82 additions and 0 deletions
|
|
@ -1,8 +1,58 @@
|
|||
import asyncio
|
||||
import logging
|
||||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from .flows.api import approvals_router, flows_router
|
||||
from .flows.sync import run_sync_blocking, watch_forever
|
||||
from .settings import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _blocking_startup_sync() -> None:
|
||||
"""One-shot reconciliation at startup (fresh session, never fatal)."""
|
||||
try:
|
||||
report = run_sync_blocking(Path(settings.flows_dir))
|
||||
logger.info(
|
||||
"startup flow sync: +%d ~%d -%d skipped=%d errors=%d",
|
||||
len(report.added),
|
||||
len(report.updated),
|
||||
len(report.deleted),
|
||||
len(report.skipped),
|
||||
len(report.errors),
|
||||
)
|
||||
for filename, reason in report.errors.items():
|
||||
logger.warning("startup flow sync: %s: %s", filename, reason)
|
||||
except FileNotFoundError as exc:
|
||||
logger.error("startup flow sync skipped: %s", exc)
|
||||
except Exception: # noqa: BLE001 - API must start even if sync fails
|
||||
logger.exception("startup flow sync failed")
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
||||
task: asyncio.Task | None = None
|
||||
stop: asyncio.Event | None = None
|
||||
if settings.flows_watch_enabled:
|
||||
await asyncio.to_thread(_blocking_startup_sync)
|
||||
stop = asyncio.Event()
|
||||
task = asyncio.create_task(
|
||||
watch_forever(stop, Path(settings.flows_dir)), name="flows-watcher"
|
||||
)
|
||||
yield
|
||||
if task is not None and stop is not None:
|
||||
stop.set()
|
||||
task.cancel()
|
||||
try:
|
||||
await task
|
||||
except (asyncio.CancelledError, Exception): # noqa: BLE001 - shutdown
|
||||
pass
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="Kirche Einfach API",
|
||||
description="KI-gestützte Verwaltungsplattform für Kirche",
|
||||
|
|
@ -10,6 +60,7 @@ app = FastAPI(
|
|||
docs_url="/api/docs",
|
||||
redoc_url="/api/redoc",
|
||||
openapi_url="/api/openapi.json",
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
app.include_router(flows_router)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue