infrarust_server_manager/
server_manager.rs

1use std::sync::Arc;
2use std::time::Duration;
3
4use tokio::sync::{Mutex, mpsc};
5use tokio::time;
6
7pub use crate::ServerState;
8use crate::api::ApiProvider;
9use crate::error::ServerManagerError;
10pub use crate::local::LocalServerConfig;
11pub use crate::monitor::{CrashDetector, ServerStatus};
12use crate::process::ProcessProvider;
13use crate::terminal::execute_command;
14
15#[derive(Debug, Clone)]
16pub struct ServerManager<T: ApiProvider> {
17    api_client: Arc<T>,
18    crash_detector: CrashDetector,
19    status_check_interval: Duration,
20    process_provider: Option<Arc<dyn ProcessProvider>>,
21}
22
23impl<T: ApiProvider> ServerManager<T> {
24    pub fn new(api_client: T) -> Self {
25        Self {
26            api_client: Arc::new(api_client),
27            crash_detector: CrashDetector::default(),
28            status_check_interval: Duration::from_secs(30),
29            process_provider: None,
30        }
31    }
32
33    pub fn with_check_interval(mut self, interval: Duration) -> Self {
34        self.status_check_interval = interval;
35        self
36    }
37
38    pub fn with_crash_detector(mut self, detector: CrashDetector) -> Self {
39        self.crash_detector = detector;
40        self
41    }
42
43    pub fn with_process_provider<P: ProcessProvider + 'static>(mut self, provider: P) -> Self {
44        self.process_provider = Some(Arc::new(provider));
45        self
46    }
47
48    pub fn api_client(&self) -> &Arc<T> {
49        &self.api_client
50    }
51
52    pub async fn monitor_server(&self, server_id: &str) -> Result<(), ServerManagerError> {
53        let server_id = server_id.to_string();
54        let api_client = Arc::clone(&self.api_client);
55        let status = Arc::new(Mutex::new(ServerStatus::new(&server_id)));
56
57        println!("Starting to monitor server: {}", server_id);
58
59        loop {
60            match api_client.get_server_status(&server_id).await {
61                Ok(api_status) => {
62                    let mut status_lock = status.lock().await;
63
64                    if api_status.is_running {
65                        status_lock.update_state(ServerState::Running);
66                    } else if api_status.is_crashed {
67                        status_lock.update_state(ServerState::Crashed);
68                    } else {
69                        status_lock.update_state(ServerState::Stopped);
70                    }
71
72                    if self.crash_detector.is_in_crash_loop(&status_lock) {
73                        println!("ALERT: Server {} is in a crash loop!", server_id);
74                    }
75
76                    println!("Server {} status: {:?}", server_id, status_lock.state);
77                }
78                Err(e) => {
79                    println!("Error checking server status: {}", e);
80                }
81            }
82
83            time::sleep(self.status_check_interval).await;
84        }
85    }
86
87    pub async fn start_server(&self, server_id: &str) -> Result<(), ServerManagerError> {
88        println!("Starting server: {}", server_id);
89        self.api_client.start_server(server_id).await
90    }
91
92    pub async fn stop_server(&self, server_id: &str) -> Result<(), ServerManagerError> {
93        println!("Stopping server: {}", server_id);
94        self.api_client.stop_server(server_id).await
95    }
96
97    pub async fn restart_server(&self, server_id: &str) -> Result<(), ServerManagerError> {
98        println!("Restarting server: {}", server_id);
99        self.api_client.restart_server(server_id).await
100    }
101
102    pub fn execute_system_command(&self, command: &str) -> Result<String, ServerManagerError> {
103        println!("Executing command: {}", command);
104        execute_command(command)
105    }
106
107    pub async fn get_server_status(
108        &self,
109        server_id: &str,
110    ) -> Result<ServerStatus, ServerManagerError> {
111        let status = self.api_client.get_server_status(server_id).await?;
112        Ok(status.into())
113    }
114
115    // ------ Methods for process interaction ------
116
117    fn ensure_process_provider(&self) -> Result<(), ServerManagerError> {
118        if self.process_provider.is_none() {
119            return Err(ServerManagerError::ProcessError(
120                "No process provider configured".to_string(),
121            ));
122        }
123        Ok(())
124    }
125
126    pub async fn write_stdin(
127        &self,
128        server_id: &str,
129        input: &str,
130    ) -> Result<(), ServerManagerError> {
131        self.ensure_process_provider()?;
132        let provider = self.process_provider.as_ref().unwrap();
133        provider.write_stdin(server_id, input).await
134    }
135
136    pub fn get_stdout_stream(
137        &self,
138        server_id: &str,
139    ) -> Result<mpsc::Receiver<String>, ServerManagerError> {
140        self.ensure_process_provider()?;
141        let provider = self.process_provider.as_ref().unwrap();
142        provider.get_stdout_stream(server_id)
143    }
144
145    pub fn is_process_running(&self, server_id: &str) -> Result<bool, ServerManagerError> {
146        self.ensure_process_provider()?;
147        let provider = self.process_provider.as_ref().unwrap();
148        provider.is_process_running(server_id)
149    }
150
151    pub async fn force_stop_process(&self, server_id: &str) -> Result<(), ServerManagerError> {
152        self.ensure_process_provider()?;
153        let provider = self.process_provider.as_ref().unwrap();
154        provider.stop_process(server_id).await
155    }
156}