aucourt-ingest/aucourt_ingest/api/app.py
slothitude f799b41ed9 Resolve all deferred audit findings: type safety, async, isolation, dates
- #11 VectorIndexProtocol for typed duck-typing of vector_index param
- #10 Wrap all sync VectorIndex.query() calls in asyncio.to_thread
- #9 Make vector_search async (consistent with to_thread wrapping)
- #12 Replace module-level singleton with app.state.query_service
- #13 InMemoryGraphDB.close(destroy=False) guard for test safety
- #14 Parse dates with datetime.fromisoformat in list_cases sort

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-30 12:20:56 +10:00

41 lines
1.2 KiB
Python

"""FastAPI app factory for the query API."""
from __future__ import annotations
from contextlib import asynccontextmanager
from fastapi import FastAPI
from aucourt_ingest.api.errors import register_error_handlers
from aucourt_ingest.api.routes import router
from aucourt_ingest.api.service import QueryService
from aucourt_ingest.storage.graph_db import GraphDB
def create_app(graph_db: GraphDB, vector_index, max_tokens: int = 4000) -> FastAPI:
"""Create and configure the FastAPI app.
Args:
graph_db: GraphDB instance (InMemoryGraphDB or Neo4jGraphDB)
vector_index: VectorIndex instance (or duck-typed fake for tests)
max_tokens: Default token budget for juror context assembly
"""
query_service = QueryService(graph_db, vector_index, max_tokens)
@asynccontextmanager
async def lifespan(app: FastAPI):
yield
await graph_db.close()
app = FastAPI(
title="AuCourtIngest Query API",
description="Read-only juror RAG query API for Australian legal cases",
version="0.1.0",
lifespan=lifespan,
)
app.state.query_service = query_service
app.include_router(router)
register_error_handlers(app)
return app