Spaces:
Configuration error
Configuration error
| from __future__ import annotations | |
| import json | |
| from fastapi import FastAPI, HTTPException, Request, status | |
| from fastapi.exceptions import RequestValidationError | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import JSONResponse | |
| from .config import get_settings | |
| from .logging_config import configure_logging, logger | |
| from .routes import api_router | |
| from .services import get_important_email_watcher, get_trigger_scheduler | |
| # Register global exception handlers for consistent error responses across the API | |
| def register_exception_handlers(app: FastAPI) -> None: | |
| async def _validation_exception_handler(request: Request, exc: RequestValidationError): | |
| logger.debug("validation error", extra={"errors": exc.errors(), "path": str(request.url)}) | |
| return JSONResponse( | |
| {"ok": False, "error": "Invalid request", "detail": exc.errors()}, | |
| status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, | |
| ) | |
| async def _http_exception_handler(request: Request, exc: HTTPException): | |
| logger.debug( | |
| "http error", | |
| extra={"detail": exc.detail, "status": exc.status_code, "path": str(request.url)}, | |
| ) | |
| detail = exc.detail | |
| if not isinstance(detail, str): | |
| detail = json.dumps(detail) | |
| return JSONResponse({"ok": False, "error": detail}, status_code=exc.status_code) | |
| async def _unhandled_exception_handler(request: Request, exc: Exception): | |
| logger.exception("Unhandled error", extra={"path": str(request.url)}) | |
| return JSONResponse( | |
| {"ok": False, "error": "Internal server error"}, | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| ) | |
| configure_logging() | |
| _settings = get_settings() | |
| app = FastAPI( | |
| title=_settings.app_name, | |
| version=_settings.app_version, | |
| docs_url=_settings.resolved_docs_url, | |
| redoc_url=None, | |
| ) | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=_settings.cors_allow_origins, | |
| allow_credentials=False, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| register_exception_handlers(app) | |
| app.include_router(api_router) | |
| # Initialize background services (trigger scheduler and email watcher) when the app starts | |
| async def _start_trigger_scheduler() -> None: | |
| scheduler = get_trigger_scheduler() | |
| await scheduler.start() | |
| watcher = get_important_email_watcher() | |
| await watcher.start() | |
| # Gracefully shutdown background services when the app stops | |
| async def _stop_trigger_scheduler() -> None: | |
| scheduler = get_trigger_scheduler() | |
| await scheduler.stop() | |
| watcher = get_important_email_watcher() | |
| await watcher.stop() | |
| __all__ = ["app"] | |