import uvicorn import asyncio import logging import sys from datetime import datetime from fastapi import FastAPI, Depends, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from sqlalchemy.orm import Session from app.api.v1.api import api_router from app.core.config import settings from app.db.session import get_db from app.core.background_tasks import task_manager # Configure logging logging.basicConfig( level=logging.DEBUG if settings.DEBUG else logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger(__name__) app = FastAPI( title=settings.PROJECT_NAME, description=settings.PROJECT_DESCRIPTION, version=settings.VERSION, openapi_url="/openapi.json", docs_url="/docs", redoc_url="/redoc", ) # Set up CORS middleware app.add_middleware( CORSMiddleware, allow_origins=settings.BACKEND_CORS_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Global exception handler @app.exception_handler(Exception) async def global_exception_handler(request: Request, exc: Exception): logger.error(f"Unhandled exception: {str(exc)}", exc_info=True) return JSONResponse( status_code=500, content={"detail": "Internal server error", "message": str(exc) if settings.DEBUG else None}, ) # Include API router app.include_router(api_router, prefix=settings.API_V1_STR) # Root endpoint @app.get("/") async def root(): return { "name": settings.PROJECT_NAME, "version": settings.VERSION, "documentation": "/docs", "health": "/health" } # Health check endpoint @app.get("/health", tags=["health"]) async def health_check(db: Session = Depends(get_db)): # Check if database is available try: # Execute a simple query db.execute("SELECT 1") db_status = "connected" except Exception as e: db_status = f"error: {str(e)}" logger.error(f"Database health check failed: {str(e)}") return { "status": "ok", "version": settings.VERSION, "timestamp": datetime.utcnow().isoformat(), "database": db_status, "environment": "production" if not settings.DEBUG else "development", } # Startup event @app.on_event("startup") async def startup_event(): logger.info("Application startup initiated") try: # Start background tasks asyncio.create_task(task_manager.start()) logger.info("Background tasks started successfully") except Exception as e: logger.error(f"Error starting background tasks: {str(e)}", exc_info=True) # Shutdown event @app.on_event("shutdown") async def shutdown_event(): logger.info("Application shutdown initiated") try: # Stop background tasks task_manager.stop() logger.info("Background tasks stopped successfully") except Exception as e: logger.error(f"Error stopping background tasks: {str(e)}", exc_info=True) if __name__ == "__main__": uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)