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 bspds::sync::listener::start_sequencer_listener(state.clone()).await;
28 let relays = std::env::var("RELAYS")
29 .unwrap_or_default()
30 .split(',')
31 .filter(|s| !s.is_empty())
32 .map(|s| s.to_string())
33 .collect();
34 bspds::sync::relay_client::start_relay_clients(state.clone(), relays, None).await;
35
36 let (shutdown_tx, shutdown_rx) = watch::channel(false);
37
38 let mut notification_service = NotificationService::new(pool);
39
40 if let Some(email_sender) = EmailSender::from_env() {
41 info!("Email notifications enabled");
42 notification_service = notification_service.register_sender(email_sender);
43 } else {
44 warn!("Email notifications disabled (MAIL_FROM_ADDRESS not set)");
45 }
46
47 let notification_handle = tokio::spawn(notification_service.run(shutdown_rx));
48
49 let app = bspds::app(state);
50
51 let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
52 info!("listening on {}", addr);
53 let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
54
55 let server_result = axum::serve(listener, app)
56 .with_graceful_shutdown(shutdown_signal(shutdown_tx))
57 .await;
58
59 notification_handle.await.ok();
60
61 if let Err(e) = server_result {
62 tracing::error!("Server error: {}", e);
63 }
64}
65
66async fn shutdown_signal(shutdown_tx: watch::Sender<bool>) {
67 let ctrl_c = async {
68 tokio::signal::ctrl_c()
69 .await
70 .expect("Failed to install Ctrl+C handler");
71 };
72
73 #[cfg(unix)]
74 let terminate = async {
75 tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate())
76 .expect("Failed to install signal handler")
77 .recv()
78 .await;
79 };
80
81 #[cfg(not(unix))]
82 let terminate = std::future::pending::<()>();
83
84 tokio::select! {
85 _ = ctrl_c => {},
86 _ = terminate => {},
87 }
88
89 info!("Shutdown signal received, stopping services...");
90 shutdown_tx.send(true).ok();
91}