From f52eec9badca7312175e0547f52de6d195dd4afa Mon Sep 17 00:00:00 2001 From: Tyler Date: Sat, 20 Jun 2026 15:36:50 -0600 Subject: [PATCH] feat(api): lifespan handler initializes EventBus + db --- backend/src/cyclone/api.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/backend/src/cyclone/api.py b/backend/src/cyclone/api.py index f8cf591..926388c 100644 --- a/backend/src/cyclone/api.py +++ b/backend/src/cyclone/api.py @@ -18,7 +18,8 @@ from __future__ import annotations import json import logging import uuid -from typing import Any, Iterator +from contextlib import asynccontextmanager +from typing import Any, AsyncIterator from fastapi import FastAPI, File, HTTPException, Query, Request, UploadFile from fastapi.middleware.cors import CORSMiddleware @@ -47,6 +48,7 @@ from cyclone.parsers.serialize_270 import serialize_270 from cyclone.parsers.serialize_999 import serialize_999 from cyclone.parsers.batch_ack_builder import build_ack_for_batch from cyclone.parsers.validator_835 import validate as validate_835 +from cyclone.pubsub import EventBus from cyclone.store import ( AlreadyMatchedError, BatchRecord, @@ -58,6 +60,18 @@ from cyclone.store import ( log = logging.getLogger(__name__) +@asynccontextmanager +async def lifespan(app: FastAPI) -> AsyncIterator[None]: + """Initialize per-process resources (DB + EventBus) before the app + serves requests. No teardown needed for Cyclone's local-only posture. + """ + from cyclone import db + + db.init_db() + app.state.event_bus = EventBus() + yield + + # Mirror cli._PAYER_FACTORIES. Kept local so the API doesn't depend on the # Click-based CLI module. PAYER_FACTORIES: dict[str, Any] = { @@ -76,6 +90,7 @@ app = FastAPI( title="Cyclone 837P / 835 Parser API", version=__version__, description="Upload X12 837P and 835 files and receive parsed records as JSON or NDJSON.", + lifespan=lifespan, ) app.add_middleware(