import logging import os import socket import sys from contextlib import asynccontextmanager import uvicorn from fastapi import FastAPI from starlette.middleware.cors import CORSMiddleware from app.api.api import api_router from app.core.config import settings # Configure logging logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler(sys.stdout)] ) logger = logging.getLogger(__name__) @asynccontextmanager async def lifespan(app: FastAPI): """ Lifespan events for the FastAPI application Handles startup and shutdown gracefully """ # Startup: Check for host availability and other system requirements try: hostname = socket.gethostname() ip_address = socket.gethostbyname(hostname) logger.info(f"Starting application on host: {hostname}, IP: {ip_address}") # Check required directories exist from pathlib import Path db_dir = Path("/app") / "storage" / "db" db_dir.mkdir(parents=True, exist_ok=True) logger.info(f"Database directory confirmed at: {db_dir}") # Set environment variable to indicate we're ready os.environ["APP_READY"] = "true" logger.info("Application startup completed successfully") except Exception as e: logger.error(f"Application startup error: {str(e)}") # Critical errors during startup should be propagated, but still allow the app to run os.environ["APP_READY"] = "false" os.environ["APP_STARTUP_ERROR"] = str(e) yield # This is where the app runs # Shutdown: Perform cleanup operations try: logger.info("Application shutting down gracefully") # Any cleanup operations would go here except Exception as e: logger.error(f"Error during application shutdown: {str(e)}") app = FastAPI( title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json", description="Generic REST API Service with FastAPI and SQLite", version="0.1.0", lifespan=lifespan, ) # Add middleware for exception handling @app.middleware("http") async def add_process_time_header(request, call_next): try: response = await call_next(request) return response except Exception as e: logger.error(f"Request error: {str(e)}") # Return error to the client from fastapi.responses import JSONResponse return JSONResponse( status_code=500, content={"detail": "Internal server error", "type": "server_error"} ) # Set all CORS enabled origins if settings.BACKEND_CORS_ORIGINS: app.add_middleware( CORSMiddleware, allow_origins=[str(origin) for origin in settings.BACKEND_CORS_ORIGINS], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(api_router, prefix=settings.API_V1_STR) if __name__ == "__main__": uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)