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}