Files
biggus-dickus/crates/api/src/health.rs
T
2026-06-02 00:58:29 +02:00

63 lines
1.7 KiB
Rust

use axum::{Json, Router, extract::State, http::StatusCode, response::IntoResponse, routing::get};
use serde::Serialize;
use utoipa::ToSchema;
use crate::AppState;
/// Liveness payload: the process is running.
#[derive(Serialize, ToSchema)]
pub(crate) struct Live {
/// Always `"ok"` when the process serves requests.
pub status: &'static str,
}
/// Readiness payload: dependencies were checked.
#[derive(Serialize, ToSchema)]
pub(crate) struct Ready {
/// `"ok"` when ready, `"degraded"` otherwise.
pub status: &'static str,
/// Whether the database responded to a ping.
pub database: bool,
}
/// Liveness probe — no dependencies checked.
#[utoipa::path(get, path = "/health/live", responses((status = 200, body = Live)))]
pub(crate) async fn live() -> Json<Live> {
Json(Live { status: "ok" })
}
/// Readiness probe — confirms the database answers.
#[utoipa::path(
get,
path = "/health/ready",
responses(
(status = 200, body = Ready, description = "Ready"),
(status = 503, body = Ready, description = "A dependency is unavailable")
)
)]
pub(crate) async fn ready(State(state): State<AppState>) -> impl IntoResponse {
match state.db.ping().await {
Ok(()) => (
StatusCode::OK,
Json(Ready {
status: "ok",
database: true,
}),
),
Err(_) => (
StatusCode::SERVICE_UNAVAILABLE,
Json(Ready {
status: "degraded",
database: false,
}),
),
}
}
/// Health routes, parameterized over [`AppState`].
pub(crate) fn routes() -> Router<AppState> {
Router::new()
.route("/health/live", get(live))
.route("/health/ready", get(ready))
}