import logging from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.api.router import api_router from app.config import settings logger = logging.getLogger("olivas") @asynccontextmanager async def lifespan(app: FastAPI): # Startup: ensure DB tables exist from app.db.session import engine from app.models.base import Base # Import all models so Base.metadata knows about them import app.models.analysis # noqa: F401 import app.models.project # noqa: F401 import app.models.aoi # noqa: F401 import app.models.comparison # noqa: F401 async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) logger.info("Database tables verified") # Startup: load ML models logger.info(f"Starting OliVAS backend (device={settings.device})") from app.services.saliency.model_manager import model_manager try: model_manager.load_models(device=settings.device) logger.info(f"Models loaded: {list(model_manager.models.keys())}") except Exception as e: logger.warning(f"Failed to load ML models: {e}. Analysis will fail until models load.") # Warm up JWKS cache for Azure AD token validation if settings.AZURE_AUTH_ENABLED and settings.AZURE_TENANT_ID: try: from app.auth import refresh_jwks_cache refresh_jwks_cache() logger.info("Azure AD JWKS cache warmed up") except Exception as e: logger.warning(f"Failed to warm JWKS cache: {e}. Will fetch on first request.") yield # Shutdown model_manager.cleanup() logger.info("OliVAS backend shut down") app = FastAPI( title="OliVAS", description="Open-Source Visual Attention Software by OLIVER", version="0.1.0", lifespan=lifespan, ) app.add_middleware( CORSMiddleware, allow_origins=settings.cors_origins_list, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(api_router)