rush_sync_server/server/
manager.rs

1// =====================================================
2// FILE: src/server/manager.rs - SERVER MANAGER
3// =====================================================
4
5use crate::core::prelude::*;
6use crate::server::{ServerInfo, ServerInstance, ServerMode, ServerStatus};
7use std::collections::HashMap;
8use std::sync::{Arc, Mutex};
9use tokio::sync::RwLock;
10
11/// Zentrale Verwaltung aller Server-Instanzen
12pub struct ServerManager {
13    pub(crate) servers: Arc<RwLock<HashMap<String, ServerInstance>>>,
14    pub(crate) config_file: std::path::PathBuf,
15}
16
17impl ServerManager {
18    /// Erstellt neuen Server-Manager
19    pub fn new() -> Self {
20        let config_file = std::path::PathBuf::from("config/servers.json");
21
22        Self {
23            servers: Arc::new(RwLock::new(HashMap::new())),
24            config_file,
25        }
26    }
27
28    /// Lädt gespeicherte Server-Konfigurationen
29    pub async fn load_servers(&self) -> Result<()> {
30        if !self.config_file.exists() {
31            log::info!("📁 No existing server config, starting fresh");
32            return Ok(());
33        }
34
35        let content = tokio::fs::read_to_string(&self.config_file)
36            .await
37            .map_err(AppError::Io)?;
38
39        let server_infos: Vec<ServerInfo> = serde_json::from_str(&content)
40            .map_err(|e| AppError::Validation(format!("Invalid server config: {}", e)))?;
41
42        let mut servers = self.servers.write().await;
43        for info in server_infos {
44            let server = ServerInstance::from_info(info);
45            servers.insert(server.get_server_id(), server);
46        }
47
48        log::info!("📊 Loaded {} servers from config", servers.len());
49        Ok(())
50    }
51
52    /// Speichert Server-Konfigurationen
53    pub async fn save_servers(&self) -> Result<()> {
54        // Config-Verzeichnis erstellen
55        if let Some(parent) = self.config_file.parent() {
56            tokio::fs::create_dir_all(parent)
57                .await
58                .map_err(AppError::Io)?;
59        }
60
61        let servers = self.servers.read().await;
62        let server_infos: Vec<ServerInfo> = servers
63            .values()
64            .map(|server| {
65                let info = server.info.lock().unwrap_or_else(|poisoned| {
66                    log::warn!("Recovered from poisoned mutex");
67                    poisoned.into_inner()
68                });
69                info.clone()
70            })
71            .collect();
72
73        let content = serde_json::to_string_pretty(&server_infos)
74            .map_err(|e| AppError::Validation(format!("Failed to serialize servers: {}", e)))?;
75
76        tokio::fs::write(&self.config_file, content)
77            .await
78            .map_err(AppError::Io)?;
79
80        log::debug!("💾 Saved {} servers to config", server_infos.len());
81        Ok(())
82    }
83
84    /// Erstellt einen neuen Server
85    pub async fn create_server(&self, port: u16, mode: ServerMode) -> Result<String> {
86        // Prüfe ob Port bereits verwendet wird
87        let servers = self.servers.read().await;
88        for server in servers.values() {
89            let info = server.info.lock().unwrap_or_else(|poisoned| {
90                log::warn!("Recovered from poisoned mutex");
91                poisoned.into_inner()
92            });
93            if info.port == port {
94                return Err(AppError::Validation(format!(
95                    "Port {} already in use",
96                    port
97                )));
98            }
99        }
100        drop(servers);
101
102        // Neuen Server erstellen
103        let server = ServerInstance::new(port, mode);
104        let server_id = server.get_server_id();
105
106        // Server zur Verwaltung hinzufügen
107        let mut servers = self.servers.write().await;
108        servers.insert(server_id.clone(), server);
109        drop(servers);
110
111        // Konfiguration speichern
112        self.save_servers().await?;
113
114        log::info!(
115            "✅ Created server {} on port {} ({})",
116            server_id,
117            port,
118            mode
119        );
120        Ok(server_id)
121    }
122
123    /// Startet einen Server
124    /// Startet einen Server
125    pub async fn start_server(&self, server_id: &str) -> Result<()> {
126        // Direkt Write-Lock holen
127        let mut servers = self.servers.write().await;
128
129        // Server direkt mutieren, KEIN Clone!
130        let server = servers
131            .get_mut(server_id)
132            .ok_or_else(|| AppError::Validation(format!("Server {} not found", server_id)))?;
133
134        // Status prüfen
135        match server.get_status() {
136            ServerStatus::Running => {
137                return Err(AppError::Validation(format!(
138                    "Server {} already running",
139                    server_id
140                )));
141            }
142            ServerStatus::Starting => {
143                return Err(AppError::Validation(format!(
144                    "Server {} already starting",
145                    server_id
146                )));
147            }
148            _ => {}
149        }
150
151        // Server direkt starten (kein Clone!)
152        server.start().await?;
153
154        // Servers lock freigeben vor save
155        drop(servers);
156
157        // Speichern
158        self.save_servers().await?;
159
160        Ok(())
161    }
162
163    /// Stoppt einen Server
164    pub async fn stop_server(&self, server_id: &str) -> Result<()> {
165        // Write-Lock direkt
166        let mut servers = self.servers.write().await;
167
168        let server = servers
169            .get_mut(server_id)
170            .ok_or_else(|| AppError::Validation(format!("Server {} not found", server_id)))?;
171
172        match server.get_status() {
173            ServerStatus::Stopped => {
174                return Err(AppError::Validation(format!(
175                    "Server {} already stopped",
176                    server_id
177                )));
178            }
179            ServerStatus::Stopping => {
180                return Err(AppError::Validation(format!(
181                    "Server {} already stopping",
182                    server_id
183                )));
184            }
185            _ => {}
186        }
187
188        // Direkt stoppen
189        server.stop().await?;
190
191        drop(servers);
192        self.save_servers().await?;
193
194        Ok(())
195    }
196
197    /// Löscht einen Server
198    pub async fn delete_server(&self, server_id: &str) -> Result<()> {
199        let mut servers = self.servers.write().await;
200
201        let server = servers
202            .get(server_id)
203            .ok_or_else(|| AppError::Validation(format!("Server {} not found", server_id)))?;
204
205        // Server muss gestoppt sein
206        match server.get_status() {
207            ServerStatus::Running | ServerStatus::Starting => {
208                return Err(AppError::Validation(format!(
209                    "Server {} must be stopped before deletion",
210                    server_id
211                )));
212            }
213            _ => {}
214        }
215
216        // Working Directory löschen
217        let working_dir = {
218            let info = server.info.lock().unwrap_or_else(|poisoned| {
219                log::warn!("Recovered from poisoned mutex");
220                poisoned.into_inner()
221            });
222            info.working_dir.clone()
223        };
224
225        if working_dir.exists() {
226            tokio::fs::remove_dir_all(&working_dir)
227                .await
228                .map_err(AppError::Io)?;
229            log::debug!("🗑️  Deleted working directory: {}", working_dir.display());
230        }
231
232        // Server aus Verwaltung entfernen
233        servers.remove(server_id);
234        drop(servers);
235
236        self.save_servers().await?;
237
238        log::info!("🗑️  Deleted server {}", server_id);
239        Ok(())
240    }
241
242    /// Liste aller Server
243    pub async fn list_servers(&self) -> Vec<String> {
244        let servers = self.servers.read().await;
245        servers.values().map(|server| server.debug_info()).collect()
246    }
247
248    /// Server-Status anzeigen
249    pub async fn get_server_status(&self, server_id: &str) -> Result<String> {
250        let servers = self.servers.read().await;
251
252        let server = servers
253            .get(server_id)
254            .ok_or_else(|| AppError::Validation(format!("Server {} not found", server_id)))?;
255
256        Ok(server.debug_info())
257    }
258
259    /// Alle Server stoppen (für Shutdown)
260    pub async fn stop_all_servers(&self) -> Result<()> {
261        let servers = self.servers.read().await;
262        let server_ids: Vec<String> = servers.keys().cloned().collect();
263        drop(servers);
264
265        for server_id in server_ids {
266            if let Err(e) = self.stop_server(&server_id).await {
267                log::warn!("Failed to stop server {}: {}", server_id, e);
268            }
269        }
270
271        Ok(())
272    }
273
274    /// Suche freien Port
275    pub async fn find_free_port(&self, start_port: u16) -> u16 {
276        let servers = self.servers.read().await;
277        let used_ports: std::collections::HashSet<u16> = servers
278            .values()
279            .map(|server| {
280                let info = server.info.lock().unwrap_or_else(|poisoned| {
281                    log::warn!("Recovered from poisoned mutex");
282                    poisoned.into_inner()
283                });
284                info.port
285            })
286            .collect();
287
288        for port in start_port..=65535 {
289            if !used_ports.contains(&port) && self.is_port_available(port).await {
290                return port;
291            }
292        }
293
294        8080 // Fallback
295    }
296
297    /// Prüft ob Port verfügbar ist
298    async fn is_port_available(&self, port: u16) -> bool {
299        use std::net::TcpListener;
300
301        TcpListener::bind(format!("127.0.0.1:{}", port)).is_ok()
302    }
303
304    /// Statistiken
305    pub async fn get_stats(&self) -> HashMap<String, usize> {
306        let servers = self.servers.read().await;
307        let mut stats = HashMap::new();
308
309        stats.insert("total".to_string(), servers.len());
310
311        let mut running = 0;
312        let mut stopped = 0;
313
314        for server in servers.values() {
315            match server.get_status() {
316                ServerStatus::Running => running += 1,
317                ServerStatus::Stopped => stopped += 1,
318                _ => {}
319            }
320        }
321
322        stats.insert("running".to_string(), running);
323        stats.insert("stopped".to_string(), stopped);
324
325        stats
326    }
327}
328
329impl Default for ServerManager {
330    fn default() -> Self {
331        Self::new()
332    }
333}
334
335impl ServerInstance {
336    /// Erstellt ServerInstance aus bestehender ServerInfo
337    pub fn from_info(info: ServerInfo) -> Self {
338        let config = crate::server::config::ServerConfig::for_mode(info.mode, info.port);
339
340        Self {
341            info: Arc::new(Mutex::new(info)),
342            config,
343            shutdown_tx: None,
344            server_handle: None,
345            file_watcher: None,
346        }
347    }
348}