Spaces:
Configuration error
Configuration error
File size: 2,860 Bytes
aa15bce |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
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:
@app.exception_handler(RequestValidationError)
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,
)
@app.exception_handler(HTTPException)
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)
@app.exception_handler(Exception)
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)
@app.on_event("startup")
# 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()
@app.on_event("shutdown")
# 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"]
|