From fd992d7e3c03f37fbcafe9d3f26c72a2ead3b2a7 Mon Sep 17 00:00:00 2001 From: Toby Vincent Date: Thu, 26 Sep 2024 17:31:16 -0500 Subject: feat!: impl full api --- src/api.rs | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 src/api.rs (limited to 'src/api.rs') diff --git a/src/api.rs b/src/api.rs new file mode 100644 index 0000000..e6a91ba --- /dev/null +++ b/src/api.rs @@ -0,0 +1,73 @@ +use std::collections::HashMap; + +use axum::{extract::State, response::IntoResponse, Json}; +use serde::{Deserialize, Serialize}; + +use crate::{service::Services, Check, Error, Status}; + +pub mod services; + +pub fn router() -> axum::Router { + use axum::routing::get; + + axum::Router::new() + .route("/healthcheck", get(healthcheck)) + .merge(services::router()) + .fallback(fallback) +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct Health { + pub status: Status, + pub output: Option, + pub checks: HashMap, +} + +impl From for Health { + fn from(value: T) -> Self { + Health { + status: Status::Fail, + output: Some(value.to_string()), + ..Default::default() + } + } +} + +impl IntoResponse for Health { + fn into_response(self) -> axum::response::Response { + Json(self).into_response() + } +} + +pub async fn healthcheck(State(services): State) -> Health { + let checks = match services.check().await { + Ok(c) => c, + Err(err) => { + return Health { + status: Status::Fail, + output: Some(err.to_string()), + ..Default::default() + } + } + }; + + let (status, output) = match checks + .values() + .filter(|s| !matches!(s.status, Status::Pass)) + .count() + { + 0 => (Status::Pass, None), + 1 => (Status::Fail, Some("1 issue detected".to_string())), + n => (Status::Fail, Some(format!("{n} issues detected"))), + }; + + Health { + status, + output, + checks, + } +} + +pub async fn fallback(uri: axum::http::Uri) -> Error { + Error::RouteNotFound(uri) +} -- cgit v1.2.3-70-g09d2