69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
"""Liveness / readiness probes.
|
|
|
|
`/health` must work with **zero** engine dependencies — it is the signal load
|
|
balancers and orchestrators use to decide whether the process is up. It
|
|
deliberately does not import or touch the pybind11 bridge.
|
|
"""
|
|
|
|
from typing import Annotated
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from pydantic import BaseModel
|
|
|
|
from app import __version__
|
|
from app.config import Settings, get_settings
|
|
from app.services import engine as engine_service
|
|
|
|
router = APIRouter(tags=["health"])
|
|
|
|
SettingsDep = Annotated[Settings, Depends(get_settings)]
|
|
|
|
|
|
class HealthResponse(BaseModel):
|
|
status: str
|
|
version: str
|
|
environment: str
|
|
engine_available: bool
|
|
# What this process can actually do. Every model path in the converter is
|
|
# fail-open, so a deploy that forgot the weights serves happily with
|
|
# Arabic recognition off and no page renderer. Without this an operator
|
|
# has to read startup logs to find that out — usually after a customer does.
|
|
capabilities: dict[str, bool] = {}
|
|
|
|
|
|
def _capabilities() -> dict[str, bool]:
|
|
"""Probe each optional capability, never raising: /health must always answer."""
|
|
caps: dict[str, bool] = {}
|
|
try:
|
|
from app.services import raster
|
|
|
|
caps["page_raster"] = raster.is_available()
|
|
except Exception:
|
|
caps["page_raster"] = False
|
|
try:
|
|
from app.services import ocr
|
|
|
|
caps["ocr"] = ocr.is_ocr_available()
|
|
caps["ocr_arabic"] = ocr.is_ocr_arabic_available()
|
|
except Exception:
|
|
caps["ocr"] = False
|
|
caps["ocr_arabic"] = False
|
|
try:
|
|
from app.services.convert.layout import ml_regions
|
|
|
|
caps["layout_ml"] = ml_regions.layout_ml_enabled() and ml_regions._weights_path().is_file()
|
|
except Exception:
|
|
caps["layout_ml"] = False
|
|
return caps
|
|
|
|
|
|
@router.get("/health", response_model=HealthResponse)
|
|
def health(settings: SettingsDep) -> HealthResponse:
|
|
return HealthResponse(
|
|
status="ok",
|
|
version=__version__,
|
|
environment=settings.environment,
|
|
engine_available=engine_service.is_available() or settings.engine_available,
|
|
capabilities=_capabilities(),
|
|
)
|