tide_disco/
healthcheck.rs

1// Copyright (c) 2022 Espresso Systems (espressosys.com)
2// This file is part of the tide-disco library.
3
4// You should have received a copy of the MIT License
5// along with the tide-disco library. If not, see <https://mit-license.org/>.
6
7use crate::StatusCode;
8use serde::{Deserialize, Serialize};
9
10/// A response to a healthcheck endpoint.
11///
12/// A type implementing [HealthCheck] may be returned from a healthcheck endpoint itself (via its
13/// [Serialize] implementation) as well as incorporated automatically into the global healthcheck
14/// endpoint for an app. The global healthcheck will fail if any of the module healthchecks return
15/// an implementation `h` of [HealthCheck] where `h.status() != StatusCode::OK`.
16///
17/// We provide a standard implementation [HealthStatus] which has variants for common states an
18/// application might encounter. We recommend using this implementation as a standard, although it
19/// is possible to implement the [HealthCheck] trait yourself if you desire more information in
20/// your healthcheck response.
21pub trait HealthCheck: Serialize {
22    /// The status of this health check.
23    ///
24    /// Should return [StatusCode::OK] if the status is considered healthy, and some other status
25    /// code if it is not.
26    fn status(&self) -> StatusCode;
27}
28
29/// Common health statuses of an application.
30#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)]
31#[serde(rename_all = "snake_case")]
32pub enum HealthStatus {
33    #[default]
34    Available,
35    Initializing,
36    Unavailabale,
37    TemporarilyUnavailable,
38    Unhealthy,
39    ShuttingDown,
40}
41
42impl HealthCheck for HealthStatus {
43    fn status(&self) -> StatusCode {
44        match self {
45            // Return healthy in normal states even if the state is not `Available`, so that load
46            // balances and health monitors don't kill the service while it is starting up or
47            // gracefully shutting down.
48            Self::Available | Self::Initializing | Self::ShuttingDown => StatusCode::OK,
49            _ => StatusCode::SERVICE_UNAVAILABLE,
50        }
51    }
52}