infrarust_server_manager/
server_manager.rs1use 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 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}