mod db; mod error; mod extract; mod handlers; mod models; #[cfg(test)] mod tests; use std::env; use axum::{Router, routing::get}; use dotenvy::dotenv; use sqlx::PgPool; use tracing_subscriber::EnvFilter; use crate::error::AppError; const BIND_ADDRESS_FALLBACK: &str = "127.0.0.1:8991"; fn router(pool: PgPool) -> Router { Router::new() .route("/health", get(handlers::health)) .route( "/measurements", get(handlers::list_measurements).post(handlers::create_measurement), ) .route("/measurements/export", get(handlers::export_measurements)) .route( "/measurements/{id}", get(handlers::get_measurement) .put(handlers::update_measurement) .delete(handlers::delete_measurement), ) .route("/metric-types", get(handlers::metric_types)) .fallback(async || AppError::NotFound) .method_not_allowed_fallback(async || AppError::MethodNotAllowed) .with_state(pool) } #[tokio::main] async fn main() -> anyhow::Result<()> { dotenv().ok(); tracing_subscriber::fmt() .with_env_filter( EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")), ) .init(); let pool = db::connect().await?; tracing::info!("connected to database"); let app = router(pool); let bind_address = env::var("HEALTH_BIND_ADDRESS").unwrap_or_else(|_| { tracing::info!("HEALTH_BIND_ADDRESS not set, falling back to {BIND_ADDRESS_FALLBACK}"); BIND_ADDRESS_FALLBACK.to_string() }); let listener = tokio::net::TcpListener::bind(bind_address).await?; tracing::info!("listening at {}", listener.local_addr()?); axum::serve(listener, app).await?; Ok(()) }