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, init_db from app.core.logging import get_logger, setup_logging from app.middleware.logging import LoggingMiddleware from app.services.extraction_processor import extraction_processor from app.services.player import initialize_player_service, shutdown_player_service from app.services.scheduler import SchedulerService from app.services.socket import socket_manager @asynccontextmanager async def lifespan(_app: FastAPI) -> AsyncGenerator[None, 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 player service await initialize_player_service(get_session_factory()) logger.info("Player service started") # Start the scheduler service scheduler_service = SchedulerService(get_session_factory()) await scheduler_service.start() logger.info("Scheduler service started") yield logger.info("Shutting down application") # Stop the scheduler service await scheduler_service.stop() logger.info("Scheduler service stopped") # Stop the player service await shutdown_player_service() logger.info("Player service 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="Soundboard API", description="API for the Soundboard application with authentication, sound management, and real-time features", version="1.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()