sui_rpc_api/service/
health.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use axum::extract::{Query, State};
5use std::time::Duration;
6use std::time::SystemTime;
7
8use crate::Result;
9use crate::RpcService;
10
11impl RpcService {
12    /// Perform a simple health check on the service.
13    ///
14    /// The threshold, or delta, between the server's system time and the timestamp in the most
15    /// recently executed checkpoint for which the server is considered to be healthy.
16    ///
17    /// If not provided, the server will be considered healthy if it can simply fetch the latest
18    /// checkpoint from its store.
19    pub fn health_check(&self, threshold_seconds: Option<u32>) -> Result<()> {
20        let summary = self.reader.inner().get_latest_checkpoint()?;
21
22        // If we have a provided threshold, check that it's close to the current time
23        if let Some(threshold_seconds) = threshold_seconds {
24            let latest_chain_time = summary.timestamp();
25
26            let threshold = SystemTime::now() - Duration::from_secs(threshold_seconds as u64);
27
28            if latest_chain_time < threshold {
29                return Err(anyhow::anyhow!(
30                    "The latest checkpoint timestamp is less than the provided threshold"
31                )
32                .into());
33            }
34        }
35
36        Ok(())
37    }
38}
39
40#[derive(Debug, serde::Serialize, serde::Deserialize)]
41pub struct Threshold {
42    /// The threshold, or delta, between the server's system time and the timestamp in the most
43    /// recently executed checkpoint for which the server is considered to be healthy.
44    ///
45    /// If not provided, the server will be considered healthy if it can simply fetch the latest
46    /// checkpoint from its store.
47    pub threshold_seconds: Option<u32>,
48}
49
50pub async fn health(
51    Query(Threshold { threshold_seconds }): Query<Threshold>,
52    State(state): State<RpcService>,
53) -> impl axum::response::IntoResponse {
54    match state.health_check(threshold_seconds) {
55        Ok(()) => (axum::http::StatusCode::OK, "up"),
56        Err(_) => (axum::http::StatusCode::SERVICE_UNAVAILABLE, "down"),
57    }
58}