From 5ca3b74e595346fb3c47c432f01319c1458cc1f5 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Thu, 1 Sep 2022 00:28:43 +0100 Subject: [PATCH] Add HTTP /health endpoint for checking database and datastore status Closes #56 --- src/err/mod.rs | 3 +++ src/net/fail.rs | 9 +++++++++ src/net/health.rs | 24 ++++++++++++++++++++++++ src/net/mod.rs | 3 +++ 4 files changed, 39 insertions(+) create mode 100644 src/net/health.rs diff --git a/src/err/mod.rs b/src/err/mod.rs index 755acad6..d0857ff9 100644 --- a/src/err/mod.rs +++ b/src/err/mod.rs @@ -23,6 +23,9 @@ pub enum Error { #[error("There was a problem with authentication")] InvalidAuth, + #[error("There was a problem connecting with the storage engine")] + InvalidStorage, + #[error("There was a problem with the database: {0}")] Db(#[from] DbError), diff --git a/src/net/fail.rs b/src/net/fail.rs index eb3f8676..5c5c00ed 100644 --- a/src/net/fail.rs +++ b/src/net/fail.rs @@ -25,6 +25,15 @@ pub async fn recover(err: warp::Rejection) -> Result Ok(warp::reply::with_status( + warp::reply::json(&Message { + code: 500, + details: Some("Health check failed".to_string()), + description: Some("The database health check for this instance failed. There was an issue with the underlying storage engine.".to_string()), + information: Some(err.to_string()), + }), + StatusCode::FORBIDDEN, + )), _ => Ok(warp::reply::with_status( warp::reply::json(&Message { code: 400, diff --git a/src/net/health.rs b/src/net/health.rs new file mode 100644 index 00000000..9beb2f12 --- /dev/null +++ b/src/net/health.rs @@ -0,0 +1,24 @@ +use crate::dbs::DB; +use crate::err::Error; +use warp::Filter; + +pub fn config() -> impl Filter + Clone { + warp::path("health").and(warp::path::end()).and(warp::get()).and_then(handler) +} + +async fn handler() -> Result { + // Get the datastore reference + let db = DB.get().unwrap(); + // Attempt to open a transaction + match db.transaction(false, false).await { + // The transaction failed to start + Err(_) => Err(warp::reject::custom(Error::InvalidStorage)), + // The transaction was successfull + Ok(mut tx) => { + // Cancel the transaction + let _ = tx.cancel().await; + // Return the response + Ok(warp::reply()) + } + } +} diff --git a/src/net/mod.rs b/src/net/mod.rs index 8d9a7be9..4a1d3e2c 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -1,6 +1,7 @@ mod export; mod fail; mod head; +mod health; mod import; mod index; mod key; @@ -28,6 +29,8 @@ pub async fn init() -> Result<(), Error> { .or(version::config()) // Status endpoint .or(status::config()) + // Health endpoint + .or(health::config()) // Signup endpoint .or(signup::config()) // Signin endpoint