use axum::extract::State;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde_json::json;
use super::super::auth::AppState;
pub async fn live() -> impl IntoResponse {
(StatusCode::OK, axum::Json(json!({ "status": "alive" })))
}
pub async fn healthz(State(state): State<AppState>) -> impl IntoResponse {
if let Some(obs) = state.shared.cluster_observer.get() {
let snap = obs.snapshot();
let label = snap.lifecycle_label();
if label == "draining" || label == "decommissioned" || label == "failed" {
let body = json!({
"status": "draining",
"lifecycle": label,
"node_id": state.shared.node_id,
});
return (StatusCode::SERVICE_UNAVAILABLE, axum::Json(body));
}
}
let health = crate::control::startup::health::observe(&state.shared.startup);
let (status, body) = crate::control::startup::health::to_http_response(&health);
(status, axum::Json(body))
}
pub async fn ready(State(state): State<AppState>) -> impl IntoResponse {
let wal_ready = state.shared.wal.next_lsn().as_u64() > 0;
let status = if wal_ready {
StatusCode::OK
} else {
StatusCode::SERVICE_UNAVAILABLE
};
let body = json!({
"status": if wal_ready { "ready" } else { "not_ready" },
"wal_lsn": state.shared.wal.next_lsn().as_u64(),
"node_id": state.shared.node_id,
});
(status, axum::Json(body))
}
pub async fn drain(State(state): State<AppState>) -> impl IntoResponse {
tracing::info!(node_id = state.shared.node_id, "drain requested via HTTP");
state.shared.shutdown.signal();
(
StatusCode::OK,
axum::Json(json!({
"status": "draining",
"node_id": state.shared.node_id,
})),
)
}