Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/introduction/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ Additional params:
- `health_checks_include_in_schema`
- `health_checks_probes`: named async callables, each returning `bool`, that the route runs on every request

The health check route on Litestar, FastAPI, FastMCP and FastStream runs every probe concurrently. On FastStream the probes run alongside the broker pings. The route returns 200 with `health_status: true` when everything passes. If any probe returns `False` or raises, the route returns 500 with the same JSON body and `health_status: false`. Each failed probe logs one warning with its name; the response body does not say which probe failed.
The health check route on Litestar, FastAPI, FastMCP and FastStream runs every probe concurrently. On FastStream the probes run alongside the broker pings. The route returns 200 with `health_status: true` when everything passes. If any probe returns `False` or raises, the route returns 503 Service Unavailable with the same JSON body and `health_status: false`. Each failed probe logs one warning with its name; the response body does not say which probe failed.

```python
import functools
Expand Down
2 changes: 1 addition & 1 deletion lite_bootstrap/bootstrappers/fastapi_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ def build_fastapi_health_check_router(self) -> "fastapi.APIRouter":
async def health_check_handler(response: fastapi.Response) -> HealthCheckTypedDict:
health_status = await self.define_health_status()
if not health_status:
response.status_code = fastapi.status.HTTP_500_INTERNAL_SERVER_ERROR
response.status_code = fastapi.status.HTTP_503_SERVICE_UNAVAILABLE
return self.render_health_check_data(health_status=health_status)

return fastapi_router
Expand Down
2 changes: 1 addition & 1 deletion lite_bootstrap/bootstrappers/fastmcp_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ async def health_check_handler(_: "Request") -> "JSONResponse":
health_status = await self.define_health_status()
return JSONResponse(
dict(self.render_health_check_data(health_status=health_status)),
status_code=status.HTTP_200_OK if health_status else status.HTTP_500_INTERNAL_SERVER_ERROR,
status_code=status.HTTP_200_OK if health_status else status.HTTP_503_SERVICE_UNAVAILABLE,
)


Expand Down
2 changes: 1 addition & 1 deletion lite_bootstrap/bootstrappers/faststream_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ async def check_health(_: object) -> "AsgiResponse":
health_status = await self.define_health_status()
return AsgiResponse(
json.dumps(self.render_health_check_data(health_status=health_status)).encode(),
200 if health_status else 500,
200 if health_status else 503,
headers={"content-type": "application/json"},
)

Expand Down
2 changes: 1 addition & 1 deletion lite_bootstrap/bootstrappers/litestar_bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ async def health_check_handler() -> litestar.Response[HealthCheckTypedDict]:
health_status = await self.define_health_status()
return litestar.Response(
self.render_health_check_data(health_status=health_status),
status_code=status_codes.HTTP_200_OK if health_status else status_codes.HTTP_500_INTERNAL_SERVER_ERROR,
status_code=status_codes.HTTP_200_OK if health_status else status_codes.HTTP_503_SERVICE_UNAVAILABLE,
)

return litestar.Router(
Expand Down
4 changes: 2 additions & 2 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ async def raising_probe() -> bool:

HEALTH_PROBE_CASES: typing.Final = [
pytest.param({"db": passing_probe, "cache": passing_probe}, 200, True, [], id="all-pass"),
pytest.param({"db": passing_probe, "cache": failing_probe}, 500, False, ["cache"], id="one-returns-false"),
pytest.param({"db": passing_probe, "cache": raising_probe}, 500, False, ["cache"], id="one-raises"),
pytest.param({"db": passing_probe, "cache": failing_probe}, 503, False, ["cache"], id="one-returns-false"),
pytest.param({"db": passing_probe, "cache": raising_probe}, 503, False, ["cache"], id="one-raises"),
]


Expand Down
6 changes: 3 additions & 3 deletions tests/test_faststream_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async def test_faststream_bootstrap_health_check_wo_broker() -> None:
test_client = TestClient(app=application)

response = test_client.get(bootstrap_config.health_checks_path)
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert response.status_code == status.HTTP_503_SERVICE_UNAVAILABLE
assert response.json() == {
"health_status": False,
"service_name": "microservice",
Expand Down Expand Up @@ -305,7 +305,7 @@ async def test_faststream_health_check_fails_when_second_broker_is_down(broker:
TestClient(app=application) as test_client,
):
response = test_client.get(config.health_checks_path)
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert response.status_code == status.HTTP_503_SERVICE_UNAVAILABLE
assert response.json()["health_status"] is False
finally:
bootstrapper.teardown()
Expand Down Expand Up @@ -573,7 +573,7 @@ async def test_faststream_health_check_fails_on_broker_ping_despite_passing_prob
finally:
bootstrapper.teardown()

assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
assert response.status_code == status.HTTP_503_SERVICE_UNAVAILABLE
assert response.json()["health_status"] is False


Expand Down
Loading