Coverage for server / routes / common / health.py: 100%

9 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-10-04 09:33 +0000

1""" 

2Readiness probe — GET /v1/health/ready. 

3 

4Companion to the two LIVENESS endpoints (`/health`, `/v1/health`), which answer 

5a static literal and are deliberately left alone: the deploy workflow points 

6HEALTH_ENDPOINT at /v1/health and rolls back when it fails, so coupling that to 

7MongoDB would let a transient database blip roll back a good deploy. 

8 

9This endpoint answers the other question — can the process actually serve? — and 

10says so with the status code, so anything that polls it needs no body parsing: 

11 

12 200 {"status": "ready", "dependencies": {"mongodb": "up"}} 

13 503 {"status": "not ready", "dependencies": {"mongodb": "down"}} 

14 

15Unauthenticated, like the liveness probes, because a probe that needs a token is 

16no use to a load balancer. That is also why the body names dependencies and 

17their state and nothing else — no connection strings, hostnames, driver 

18messages or stack traces. 

19 

20JIRA / Zephyr: EI-T419 / EI-T421 (Edge_System_Health — the probe reflects a 

21downstream dependency outage) 

22Developer: Allan Ninal 

23Date: 2026-09-21 

24""" 

25 

26from fastapi import APIRouter, Response, status 

27 

28from server.connection.database import client as mongo_client 

29from server.utilities.readiness import check_dependencies 

30 

31router = APIRouter() 

32 

33 

34@router.get( 

35 "/ready", 

36 tags=["Server Health Check"], 

37 summary="Check whether the server can serve requests", 

38 description=( 

39 "Readiness probe. Answers 200 when every dependency is reachable and " 

40 "503 when one is not, so a caller can rely on the status code alone. " 

41 "Unauthenticated, and deliberately discloses nothing beyond each " 

42 "dependency name and whether it is up." 

43 ), 

44 responses={ 

45 200: {"description": "Every dependency is reachable"}, 

46 503: {"description": "At least one dependency is unreachable"}, 

47 }, 

48) 

49async def readiness(response: Response) -> dict: 

50 ready, dependencies = await check_dependencies(mongo_client) 

51 response.status_code = ( 

52 status.HTTP_200_OK if ready else status.HTTP_503_SERVICE_UNAVAILABLE 

53 ) 

54 return {"status": "ready" if ready else "not ready", "dependencies": dependencies}