arminius_lib_component/probes.rs
1// SPDX-FileCopyrightText: 2026 BWI GmbH
2//
3// SPDX-License-Identifier: Apache-2.0
4
5//! Module containing Axum routes and handlers for the observability probe
6//! endpoints
7
8mod tests;
9
10use axum::{Router, extract::State, http::StatusCode, routing::get};
11
12use crate::ServerState;
13
14/// Create the observability probe routes. These are meant to be mounted
15/// outside the middleware stack, so that they are not traced.
16pub fn probe_router(state: ServerState) -> Router {
17 let probes = Router::new()
18 .route("/readyz", get(ready_handler))
19 .route("/startupz", get(startup_handler))
20 .with_state(state)
21 .route("/livez", get(live_handler));
22
23 Router::new().nest("/status", probes)
24}
25
26/// Handler for `GET /status/readyz`
27/// (See <https://kubernetes.io/docs/concepts/workloads/pods/probes/#readiness-probe>).
28///
29/// Readiness probe. Should succeed whenever the application is running and
30/// ready to accept traffic. This means also checking whether dependent
31/// services like Postgres and NATS are available.
32async fn ready_handler(State(state): State<ServerState>) -> StatusCode {
33 let database_ready = database_ready(&state).await;
34 let nats_ready = nats_ready(&state.nats_connection.client.connection_state());
35
36 if database_ready && nats_ready { StatusCode::OK } else { StatusCode::SERVICE_UNAVAILABLE }
37}
38
39/// Whether the NATS connection is established. Logs a warning if it is not.
40fn nats_ready(state: &async_nats::connection::State) -> bool {
41 match state {
42 async_nats::connection::State::Connected => true,
43 async_nats::connection::State::Disconnected | async_nats::connection::State::Pending => {
44 tracing::warn!(%state, "NATS is not ready");
45 false
46 }
47 }
48}
49
50/// Whether the DB connection is established. Logs a warning if it is not.
51async fn database_ready(state: &ServerState) -> bool {
52 state
53 .database
54 .ping()
55 .await
56 .inspect_err(|error| tracing::warn!(%error, "Database is not ready"))
57 .is_ok()
58}
59
60/// Handler for `GET /status/livez`
61/// (See <https://kubernetes.io/docs/concepts/workloads/pods/probes/#liveness-probe>).
62///
63/// Liveness probe. Should succeed whenever the application is running, and is
64/// used to detect things like deadlocks. Times out when the tokio runtime is
65/// not able to schedule the task.
66///
67/// Note: This endpoint simply returns 200. In practice this checks whether the
68/// runtime can schedule tasks. It currently does not detect if there are other
69/// tasks that are deadlocked, or other problems with liveness.
70async fn live_handler() {}
71
72/// Handler for `GET /status/startupz`
73/// (See <https://kubernetes.io/docs/concepts/workloads/pods/probes/#startup-probe>).
74///
75/// Startup probe. Should succeed only when the application is started,
76/// signalling to kubernetes that it can begin to run readiness and liveness
77/// probes.
78///
79/// Note: This endpoint simply returns 200, as Axum being able to serve routes
80/// is one of the last things done during service initialization.
81async fn startup_handler() {}