actually make readyz useful

This commit is contained in:
Charlotte 🦝 Delenk 2024-11-28 15:44:45 +01:00
parent d924902cc0
commit 0f17d1cbae
Signed by: darkkirb
GPG key ID: AB2BD8DAF2E37122
3 changed files with 63 additions and 6 deletions

View file

@ -0,0 +1,20 @@
{
"db_name": "PostgreSQL",
"query": "SELECT 1 as running",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "running",
"type_info": "Int4"
}
],
"parameters": {
"Left": []
},
"nullable": [
null
]
},
"hash": "882da6c909603e0916ea9971dafe30de43484ab9c574f6ae0c01331419bf9c31"
}

View file

@ -1,9 +1,9 @@
//! Chir.rs database models
use std::sync::Arc;
use std::{sync::Arc, time::Duration};
use eyre::{Context, Result};
use sqlx::{migrate, PgPool};
use eyre::{eyre, Context, Result};
use sqlx::{migrate, query, PgPool};
use tracing::instrument;
pub mod file;
@ -13,6 +13,29 @@ pub mod file;
#[repr(transparent)]
pub struct Database(Arc<PgPool>);
impl Database {
/// This function verifies an active connection to the database.
///
/// # Errors
/// This function returns an error if the database connection has failed or a timeout of 1s occurred
#[instrument]
pub async fn ping(&self) -> Result<()> {
let fut = async {
match query!("SELECT 1 as running").fetch_one(&*self.0).await {
Ok(v) if v.running == Some(1) => Ok::<_, eyre::Report>(()),
Err(e) => Err(e).context("Checking for readiness"),
r => Err(eyre!("Unknown database response: {r:#?}")),
}
};
tokio::time::timeout(Duration::from_secs(1), fut)
.await
.context("Awaiting a ping")??;
Ok(())
}
}
/// Opens the database
///
/// # Errors

View file

@ -4,7 +4,7 @@ use std::sync::Arc;
use axum::{
extract::{MatchedPath, Request, State},
http::Response,
http::{Response, StatusCode},
response::IntoResponse,
routing::get,
Router,
@ -17,7 +17,7 @@ use chir_rs_http_api::{axum::bincode::Bincode, readiness::ReadyState};
use eyre::{Context, Result};
use tokio::net::TcpListener;
use tower_http::trace::TraceLayer;
use tracing::{info, info_span};
use tracing::{error, info, info_span};
/// Application state
#[derive(Clone, Debug)]
@ -48,7 +48,21 @@ pub async fn main(cfg: Arc<ChirRs>, db: Database, castore: CaStore) -> Result<()
let (prometheus_layer, metric_handle) = PrometheusMetricLayer::pair();
let app = Router::new()
// Routes here
.route("/.api/readyz", get(|| async { Bincode(ReadyState::Ready) }))
.route(
"/.api/readyz",
get(|State(state): State<AppState>| async move {
match state.db.ping().await {
Ok(()) => (StatusCode::OK, Bincode(ReadyState::Ready)),
Err(e) => {
error!("Database is not responding: {e:?}");
(
StatusCode::INTERNAL_SERVER_ERROR,
Bincode(ReadyState::NotReady),
)
}
}
}),
)
.route(
"/.api/metrics",
get(|| async move { metric_handle.render() }),