File size: 2,244 Bytes
1086e43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Exception handlers mapping domain errors to HTTP responses."""

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

from app.extraction.mineru_client import MinerUError


class DocumentNotFound(Exception):
    def __init__(self, document_id: str):
        self.document_id = document_id


class ChunkNotFound(Exception):
    def __init__(self, chunk_id: str):
        self.chunk_id = chunk_id


class ModelUnavailable(Exception):
    def __init__(self, model: str):
        self.model = model


class NoLLMConfigured(ModelUnavailable):
    """Neither Ollama nor any cloud API key is usable. The message carries
    full instructions, so handlers surface it verbatim (no prefix)."""


def register_exception_handlers(app: FastAPI) -> None:
    """Register all domain exception handlers."""

    @app.exception_handler(DocumentNotFound)
    async def document_not_found_handler(request: Request, exc: DocumentNotFound):
        return JSONResponse(
            status_code=404,
            content={"detail": f"Document not found: {exc.document_id}", "code": "DOCUMENT_NOT_FOUND"},
        )

    @app.exception_handler(ChunkNotFound)
    async def chunk_not_found_handler(request: Request, exc: ChunkNotFound):
        return JSONResponse(
            status_code=404,
            content={"detail": f"Chunk not found: {exc.chunk_id}", "code": "CHUNK_NOT_FOUND"},
        )

    @app.exception_handler(NoLLMConfigured)
    async def no_llm_configured_handler(request: Request, exc: NoLLMConfigured):
        return JSONResponse(
            status_code=503,
            content={"detail": str(exc.model), "code": "NO_LLM_CONFIGURED"},
        )

    @app.exception_handler(ModelUnavailable)
    async def model_unavailable_handler(request: Request, exc: ModelUnavailable):
        return JSONResponse(
            status_code=503,
            content={"detail": f"Model unavailable: {exc.model}", "code": "MODEL_UNAVAILABLE"},
        )

    @app.exception_handler(MinerUError)
    async def extraction_error_handler(request: Request, exc: MinerUError):
        return JSONResponse(
            status_code=500,
            content={"detail": f"Extraction failed: {exc}", "code": "EXTRACTION_FAILED"},
        )