1use std::sync::Arc;
2use tokio::signal;
3use tokio::task::JoinHandle;
4use tracing::{info, error};
5use ferrox_errors::AppError;
6use ferrox_transports::Transport;
7
8pub struct FerroxApp {
9 transports: Vec<Arc<dyn Transport>>,
10}
11
12impl Default for FerroxApp {
13 fn default() -> Self {
14 Self::new()
15 }
16}
17
18impl FerroxApp {
19 pub fn new() -> Self {
20 Self {
21 transports: Vec::new(),
22 }
23 }
24
25 pub fn add_transport<T: Transport + 'static>(mut self, transport: T) -> Self {
27 self.transports.push(Arc::new(transport));
28 self
29 }
30
31 pub async fn start(self) -> Result<(), AppError> {
33 info!("Starting FerroxApp multi-transport system...");
34
35 if self.transports.is_empty() {
36 return Err(AppError::InternalServerError(
37 "Cannot start FerroxApp: no transports configured!".into(),
38 ));
39 }
40
41 let mut join_handles: Vec<JoinHandle<Result<(), AppError>>> = Vec::new();
42
43 for transport in self.transports {
44 let t = Arc::clone(&transport);
45
46 let handle = tokio::spawn(async move {
47 info!("Booting transport: {}", t.name());
48 if let Err(e) = t.start().await {
49 error!("Transport {} crashed: {:?}", t.name(), e);
50 return Err(e);
51 }
52 Ok(())
53 });
54
55 join_handles.push(handle);
56 }
57
58 shutdown_signal().await;
60
61 info!("Graceful shutdown initiated...");
62
63 for handle in join_handles {
65 handle.abort();
66 }
67
68 info!("FerroxApp stopped gracefully.");
69 Ok(())
70 }
71}
72
73async fn shutdown_signal() {
74 let ctrl_c = async {
75 signal::ctrl_c()
76 .await
77 .expect("failed to install Ctrl+C handler");
78 };
79
80 #[cfg(unix)]
81 let terminate = async {
82 signal::unix::signal(signal::unix::SignalKind::terminate())
83 .expect("failed to install signal handler")
84 .recv()
85 .await;
86 };
87
88 #[cfg(not(unix))]
89 let terminate = std::future::pending::<()>();
90
91 tokio::select! {
92 _ = ctrl_c => {},
93 _ = terminate => {},
94 }
95
96 info!("Shutdown signal received, starting graceful shutdown...");
97}
98
99pub fn setup() {
100 println!("ferrox-app initialized: Multi-Transport FerroxApp bootstrap ready.");
101}