43 lines
1.9 KiB
Python
43 lines
1.9 KiB
Python
from fastapi import APIRouter, Depends
|
|
|
|
from haiku.rag.ingester.api.schemas import HealthResponse
|
|
from haiku.rag.ingester.api.server import APIState, get_state
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/health", response_model=HealthResponse)
|
|
async def health(state: APIState = Depends(get_state)) -> HealthResponse:
|
|
"""Liveness signal + queue/worker overview. Unauthenticated so load
|
|
balancers and uptime monitors can hit it without a token.
|
|
|
|
`status="degraded"` when at least one configured worker or poller task
|
|
has died (workers_alive < worker_count or pollers_alive < poller_count).
|
|
The DB query alone can't catch that — workers might be all dead and the
|
|
queue would still report counts cheerfully — so this branch is what
|
|
actually distinguishes "alive" from "alive but doing nothing useful".
|
|
"""
|
|
counts = await state.job_repo.counts_by_status()
|
|
worker_count = (
|
|
state.config.ingester.workers.worker_count if state.pool is not None else 0
|
|
)
|
|
workers_alive = state.pool.live_workers if state.pool is not None else 0
|
|
poller_count = len(state.pollers.pollers) if state.pollers is not None else 0
|
|
pollers_alive = state.pollers.live_pollers if state.pollers is not None else 0
|
|
breaker_open = state.pool.breaker_open if state.pool is not None else False
|
|
breaker_failures = (
|
|
state.pool.breaker_consecutive_failures if state.pool is not None else 0
|
|
)
|
|
degraded = (
|
|
workers_alive < worker_count or pollers_alive < poller_count or breaker_open
|
|
)
|
|
return HealthResponse(
|
|
status="degraded" if degraded else "ok",
|
|
queue_counts=counts,
|
|
worker_count=worker_count,
|
|
poller_count=poller_count,
|
|
workers_alive=workers_alive,
|
|
pollers_alive=pollers_alive,
|
|
worker_breaker_open=breaker_open,
|
|
worker_breaker_consecutive_failures=breaker_failures,
|
|
)
|