this repo has no description
1use bspds::notifications::{EmailSender, NotificationService}; 2use bspds::state::AppState; 3use std::net::SocketAddr; 4use tokio::sync::watch; 5use tracing::{info, warn}; 6 7#[tokio::main] 8async fn main() { 9 dotenvy::dotenv().ok(); 10 tracing_subscriber::fmt::init(); 11 12 let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 13 14 let pool = sqlx::postgres::PgPoolOptions::new() 15 .max_connections(5) 16 .connect(&database_url) 17 .await 18 .expect("Failed to connect to Postgres"); 19 20 sqlx::migrate!("./migrations") 21 .run(&pool) 22 .await 23 .expect("Failed to run migrations"); 24 25 let state = AppState::new(pool.clone()).await; 26 27 let (shutdown_tx, shutdown_rx) = watch::channel(false); 28 29 let mut notification_service = NotificationService::new(pool); 30 31 if let Some(email_sender) = EmailSender::from_env() { 32 info!("Email notifications enabled"); 33 notification_service = notification_service.register_sender(email_sender); 34 } else { 35 warn!("Email notifications disabled (MAIL_FROM_ADDRESS not set)"); 36 } 37 38 let notification_handle = tokio::spawn(notification_service.run(shutdown_rx)); 39 40 let app = bspds::app(state); 41 42 let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); 43 info!("listening on {}", addr); 44 let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); 45 46 let server_result = axum::serve(listener, app) 47 .with_graceful_shutdown(shutdown_signal(shutdown_tx)) 48 .await; 49 50 notification_handle.await.ok(); 51 52 if let Err(e) = server_result { 53 tracing::error!("Server error: {}", e); 54 } 55} 56 57async fn shutdown_signal(shutdown_tx: watch::Sender<bool>) { 58 let ctrl_c = async { 59 tokio::signal::ctrl_c() 60 .await 61 .expect("Failed to install Ctrl+C handler"); 62 }; 63 64 #[cfg(unix)] 65 let terminate = async { 66 tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) 67 .expect("Failed to install signal handler") 68 .recv() 69 .await; 70 }; 71 72 #[cfg(not(unix))] 73 let terminate = std::future::pending::<()>(); 74 75 tokio::select! { 76 _ = ctrl_c => {}, 77 _ = terminate => {}, 78 } 79 80 info!("Shutdown signal received, stopping services..."); 81 shutdown_tx.send(true).ok(); 82}