use axum::Router; use config::config; use sqlx::{postgres::PgPoolOptions, PgPool}; use std::time::Duration; use tokio::net::TcpListener; use tokio::signal; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; mod config; mod datasources; mod routes; pub struct AppState { db: PgPool, } #[tokio::main] async fn main() { let _ = config(); tracing_subscriber::registry() .with( tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { format!( "{}=debug,tower_http=debug,axum=trace", env!("CARGO_CRATE_NAME") ) .into() }), ) .with(tracing_subscriber::fmt::layer()) .init(); let db_connection_str = std::env::var("DATABASE_URL").unwrap(); // .unwrap_or_else(|_| "postgres://postgres:password@localhost".to_string()); // set up connection pool let pool = PgPoolOptions::new() .max_connections(10) .acquire_timeout(Duration::from_secs(3)) .connect(&db_connection_str) .await .expect("Failed to connect to database"); let app_state = AppState { db: pool.clone() }; // build our application with some routes let app = Router::new() .nest("/", routes::root::RootRoute::routes()) .nest("/posts", routes::posts::PostsRoute::routes(&app_state)) .nest( "/comments", routes::comments::CommentsRoute::routes(&app_state), ); // run it with hyper let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap(); tracing::debug!("listening on {}", listener.local_addr().unwrap()); axum::serve(listener, app) .with_graceful_shutdown(shutdown_signal()) .await .unwrap(); } async fn shutdown_signal() { let ctrl_c = async { signal::ctrl_c() .await .expect("Failed to install Ctrl+C handler"); }; #[cfg(unix)] let terminate = async { signal::unix::signal(signal::unix::SignalKind::terminate()) .expect("Failed to install signal handler") .recv() .await; }; #[cfg(not(unix))] let terminate = std::future::pending::<()>(); tokio::select! { _ = ctrl_c => {}, _ = terminate => {}, } }