actually make readyz useful
This commit is contained in:
parent
d924902cc0
commit
0f17d1cbae
3 changed files with 63 additions and 6 deletions
|
@ -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"
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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() }),
|
||||
|
|
Loading…
Reference in a new issue