from collections.abc import AsyncGenerator from contextlib import asynccontextmanager import socketio from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from app.api import api_router from app.core.config import settings from app.core.database import get_session_factory from app.core.logging import get_logger, setup_logging from app.core.services import app_services from app.middleware.logging import LoggingMiddleware from app.services.extraction_processor import extraction_processor from app.services.player import ( get_player_service, initialize_player_service, shutdown_player_service, ) from app.services.scheduler import SchedulerService from app.services.socket import socket_manager from app.services.tts_processor import tts_processor @asynccontextmanager async def lifespan(_app: FastAPI) -> AsyncGenerator[None]: """Application lifespan context manager for setup and teardown.""" setup_logging() logger = get_logger(__name__) logger.info("Starting application") # await init_db() # logger.info("Database initialized") # Start the extraction processor await extraction_processor.start() logger.info("Extraction processor started") # Start the TTS processor await tts_processor.start() logger.info("TTS processor started") # Start the player service await initialize_player_service(get_session_factory()) logger.info("Player service started") # Start the scheduler service try: player_service = get_player_service() # Get the initialized player service app_services.scheduler_service = SchedulerService( get_session_factory(), player_service, ) await app_services.scheduler_service.start() logger.info("Enhanced scheduler service started") except Exception: logger.exception("Failed to start scheduler service - continuing without it") app_services.scheduler_service = None yield logger.info("Shutting down application") # Stop the scheduler service if app_services.scheduler_service: await app_services.scheduler_service.stop() logger.info("Scheduler service stopped") # Stop the player service await shutdown_player_service() logger.info("Player service stopped") # Stop the TTS processor await tts_processor.stop() logger.info("TTS processor stopped") # Stop the extraction processor await extraction_processor.stop() logger.info("Extraction processor stopped") def create_app() -> FastAPI: """Create and configure the FastAPI application.""" app = FastAPI( title="SBD v2 API", description=("API for the SBD v2 application"), version="2.0.0", lifespan=lifespan, # Configure docs URLs for reverse proxy setup docs_url="/api/docs", # Swagger UI at /api/docs redoc_url="/api/redoc", # ReDoc at /api/redoc openapi_url="/api/openapi.json", # OpenAPI schema at /api/openapi.json ) # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.add_middleware(LoggingMiddleware) # Include API routes app.include_router(api_router) # Create Socket.IO app with fallback to FastAPI app return socketio.ASGIApp(socket_manager.sio, app) app = create_app()