//! tidalDB + Axum: embedding a tidalDB instance in an Axum web server. //! //! Demonstrates: //! - Wrapping `TidalDb` in `Arc` for shared ownership across handler threads //! - Passing the instance via Axum `State>` //! - A `/health` route that calls `health_check()` //! - Graceful shutdown via `tokio::signal::ctrl_c()` //! //! `TidalDb` is not `Clone`, so it must be wrapped in `Arc` for use with //! Axum's `State`, which requires `T: Clone + Send + Sync + 'static`. //! //! # Running //! //! ```bash //! cargo run --example axum_embedding --manifest-path tidal/Cargo.toml //! # Then: curl http://127.0.0.1:3000/health //! ``` use std::sync::Arc; use axum::{Router, extract::State, routing::get}; use tidaldb::TidalDb; async fn health(State(db): State>) -> &'static str { match db.health_check() { Ok(()) => "ok", Err(_) => "degraded", } } /// Resolves when Ctrl+C is received. async fn shutdown_signal() { tokio::signal::ctrl_c() .await .unwrap_or_else(|e| eprintln!("ctrl-c error: {e}")); } #[tokio::main] async fn main() -> Result<(), Box> { tracing_subscriber::fmt() .with_env_filter("tidaldb=debug") .init(); // `TidalDb` is not Clone — wrap in Arc so the router and main both hold a // reference. The router clone gets the weak reference; main retains the // strong reference for explicit shutdown ordering. let db = Arc::new(TidalDb::builder().ephemeral().open()?); let app = Router::new() .route("/health", get(health)) .with_state(Arc::clone(&db)); let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?; let addr = listener.local_addr()?; println!("listening on http://{addr}"); println!(" GET /health -> tidalDB health check"); println!("press Ctrl+C to stop"); axum::serve(listener, app) .with_graceful_shutdown(shutdown_signal()) .await?; // `db` drops here, calling TidalDb::drop() -> shutdown_inner(). // Future milestones: WAL drain and storage flush happen in close(). Ok(()) }