import sys from contextlib import asynccontextmanager import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from loguru import logger from app.api import router as api_router from app.config import settings from app.database import check_database, engine, init_db_schema from app.dependencies import camera_session_manager logger.remove() logger.add( sys.stderr, format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}", ) @asynccontextmanager async def lifespan(app: FastAPI): await check_database() await init_db_schema() logger.info("Database connection verified and schema ensured") await camera_session_manager.start_archive_retry_loop() yield await camera_session_manager.shutdown() await engine.dispose() logger.info("Database engine disposed") def create_app() -> FastAPI: application = FastAPI( title="Operation Room Monitor", lifespan=lifespan, ) if settings.demo_cors_enabled: origins = settings.parsed_demo_cors_origins() if origins: application.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=origins != ["*"], allow_methods=["*"], allow_headers=["*"], ) logger.info("CORS enabled for demo client; origins={}", origins) application.include_router(api_router) if settings.demo_orchestrator_enabled: from app.routers import demo_orch application.include_router(demo_orch.router) logger.info( "Demo orchestrator enabled: POST /internal/demo/orchestrate-and-start", ) else: logger.info( "Demo orchestrator disabled (DEMO_ORCHESTRATOR_ENABLED=false): " "GET /internal/demo/orchestrator-status for status; " "POST /internal/demo/orchestrate-and-start is not registered", ) return application app = create_app() def main() -> None: uvicorn.run( "main:app", host="0.0.0.0", port=38080, reload=True, ) if __name__ == "__main__": main()