mina_node_native/http_server/routes/
status.rs1use axum::{extract::State, Json};
10use utoipa_axum::{router::OpenApiRouter, routes};
11
12use mina_node::{
13 rpc::{
14 RpcHealthCheckResponse, RpcHeartbeatGetResponse, RpcNodeStatus, RpcReadinessCheckResponse,
15 RpcRequest, RpcStatusGetResponse,
16 },
17 BuildEnv,
18};
19
20use crate::http_server::{AppError, AppResult, AppState, JsonErrorResponse};
21
22pub fn routes() -> OpenApiRouter<AppState> {
24 OpenApiRouter::new()
25 .routes(routes!(build_env))
26 .routes(routes!(status))
27 .routes(routes!(healthz))
28 .routes(routes!(readyz))
29 .routes(routes!(make_heartbeat))
30}
31
32#[utoipa::path(
34 get,
35 path = "/build_env",
36 tag = "status",
37 responses(
38 (status = 200, body = BuildEnv)
39 )
40)]
41async fn build_env() -> Json<BuildEnv> {
42 Json(mina_node::BuildEnv::get())
43}
44
45#[utoipa::path(
47 get,
48 path = "/status",
49 tag = "status",
50 responses(
51 (status = 200, description = "Current node status", body = RpcNodeStatus)
52 )
53)]
54async fn status(State(state): State<AppState>) -> AppResult<Json<RpcNodeStatus>> {
55 let reply: RpcStatusGetResponse = rpc_request!(state, RpcRequest::StatusGet)?;
56 reply.map(Json).ok_or(AppError::Internal(
57 "StatusGet should always return Some(...)".into(),
58 ))
59}
60
61#[utoipa::path(
63 get,
64 path = "/healthz",
65 tags = ["status", "kubernetes"],
66 responses(
67 (status = 200, description = "Node is healthy"),
68 (status = 503, description = "Node is unhealthy", body = JsonErrorResponse,
69 examples(
70 ("NoReadyPeers" = (value = json!({"error": "no ready peers"}))),
71 ))
72 )
73)]
74async fn healthz(State(state): State<AppState>) -> AppResult<()> {
75 let reply: RpcHealthCheckResponse = rpc_request!(state, RpcRequest::HealthCheck)?;
76 reply.map_err(AppError::ServiceUnavailable)
77}
78
79#[utoipa::path(
81 get,
82 path = "/readyz",
83 tags = ["status", "kubernetes"],
84 responses(
85 (status = 200, description = "Node is ready to accept traffic"),
86 (status = 503, description = "Node is not ready", body = JsonErrorResponse,
87 examples(
88 ("NotSynced" = (value = json!({"error": "not synced"}))),
89 ("Desynced" = (value = json!({"error": "Synced 2000s ago, which is more than the threshold 1800s"}))),
90 )),
91 )
92)]
93async fn readyz(State(state): State<AppState>) -> AppResult<()> {
94 let reply: RpcReadinessCheckResponse = rpc_request!(state, RpcRequest::ReadinessCheck)?;
95 reply.map_err(AppError::ServiceUnavailable)
96}
97
98#[utoipa::path(
100 post,
101 path = "/make_heartbeat",
102 tag = "status",
103 responses(
104 (status = 200, description = "Heartbeat triggered successfully", body = inline(RpcHeartbeatGetResponse))
106 )
107)]
108async fn make_heartbeat(State(state): State<AppState>) -> AppResult<Json<RpcHeartbeatGetResponse>> {
109 jsonify_rpc!(state, RpcRequest::HeartbeatGet)
110}