from collections.abc import AsyncGenerator from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from sqlalchemy import text from app.config import settings from app.db import AsyncSessionLocal, engine from app.routers import routers @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: async with AsyncSessionLocal() as session: try: await session.execute(text("SELECT 1")) except Exception: import logging logging.getLogger(__name__).warning("Database connectivity check failed on startup") yield await engine.dispose() app = FastAPI( title=settings.app_name, debug=settings.debug, lifespan=lifespan, ) allow_origins = ["*"] if settings.debug else [] app.add_middleware( CORSMiddleware, allow_origins=allow_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) for router in routers: app.include_router(router, prefix=settings.api_v1_prefix) @app.get("/health") async def health() -> JSONResponse: db_status = "connected" try: async with AsyncSessionLocal() as session: await session.execute(text("SELECT 1")) except Exception: db_status = "unreachable" content = { "status": "ok" if db_status == "connected" else "degraded", "service": settings.app_name, "database": db_status, } status_code = 200 if db_status == "connected" else 503 return JSONResponse(status_code=status_code, content=content)