""" FastAPI Main Application """ import sys import os from pathlib import Path from contextlib import asynccontextmanager from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from loguru import logger from app.config import settings from app.core.redis_client import get_redis_client from app.api.routes import router # Configure logging logger.remove() logger.add( sys.stdout, format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}", level=settings.LOG_LEVEL ) # Create logs directory if it doesn't exist try: log_dir = Path("logs") log_dir.mkdir(parents=True, exist_ok=True) logger.add( "logs/swara_api_{time:YYYY-MM-DD}.log", rotation="1 day", retention="7 days", format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}", level=settings.LOG_LEVEL ) except (PermissionError, OSError) as e: # If we can't write to logs directory, only use stdout logger.warning(f"Cannot create log file: {e}. Using stdout only.") @asynccontextmanager async def lifespan(app: FastAPI): """ Application lifespan events """ # Startup logger.info("=" * 70) logger.info("🚀 SWARA API Starting...") logger.info("=" * 70) logger.info(f"Environment: {settings.ENV}") logger.info(f"API Version: {settings.API_VERSION}") logger.info(f"Redis URL: {settings.REDIS_URL}") # Connect to Redis try: redis_client = get_redis_client() redis_client.connect() logger.info("✓ Redis connection established") except Exception as e: logger.error(f"✗ Failed to connect to Redis: {e}") logger.warning("⚠ API will start but background tasks will not work") # Create necessary directories settings.get_temp_dir() settings.get_models_dir() logger.info("✓ Directories created") logger.info("=" * 70) logger.info(f"✓ SWARA API Ready at http://{settings.API_HOST}:{settings.API_PORT}") logger.info("=" * 70) yield # Shutdown logger.info("=" * 70) logger.info("🛑 SWARA API Shutting down...") logger.info("=" * 70) # Disconnect from Redis try: redis_client = get_redis_client() redis_client.disconnect() logger.info("✓ Redis disconnected") except: pass logger.info("✓ Shutdown complete") logger.info("=" * 70) # Create FastAPI application app = FastAPI( title=settings.API_TITLE, version=settings.API_VERSION, description=settings.API_DESCRIPTION, lifespan=lifespan, docs_url="/docs", redoc_url="/redoc", openapi_url="/openapi.json" ) # CORS Middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], # In production, specify allowed origins allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Include routers app.include_router(router) # Global exception handler @app.exception_handler(Exception) async def global_exception_handler(request, exc): """Global exception handler""" logger.error(f"Unhandled exception: {exc}") return JSONResponse( status_code=500, content={ "error": "Internal server error", "detail": str(exc) if settings.ENV == "development" else "An unexpected error occurred" } ) if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host=settings.API_HOST, port=settings.API_PORT, reload=settings.ENV == "development", workers=settings.API_WORKERS )