rush_sync_server/commands/start/
command.rs

1// StartCommand - src/commands/start/command.rs
2use crate::commands::command::Command;
3use crate::core::prelude::*;
4use crate::server::handlers::web::create_web_server;
5use crate::server::types::{ServerContext, ServerStatus};
6use crate::server::utils::{port::is_port_available, validation::find_server};
7use std::future::Future;
8use std::pin::Pin;
9
10#[derive(Debug, Default)]
11pub struct StartCommand;
12
13impl StartCommand {
14    pub fn new() -> Self {
15        Self
16    }
17}
18
19impl Command for StartCommand {
20    fn name(&self) -> &'static str {
21        "start"
22    }
23    fn description(&self) -> &'static str {
24        "Start a web server"
25    }
26    fn matches(&self, command: &str) -> bool {
27        command.trim().to_lowercase().starts_with("start")
28    }
29
30    fn execute_sync(&self, args: &[&str]) -> Result<String> {
31        if args.is_empty() {
32            return Err(AppError::Validation(
33                "Server-ID/Name fehlt! Verwende 'start <ID>'".to_string(),
34            ));
35        }
36
37        let ctx = crate::server::shared::get_shared_context();
38        self.start_server_async(ctx, args[0])
39    }
40
41    fn execute_async<'a>(
42        &'a self,
43        args: &'a [&'a str],
44    ) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>> {
45        Box::pin(async move { self.execute_sync(args) })
46    }
47
48    fn supports_async(&self) -> bool {
49        true
50    }
51    fn priority(&self) -> u8 {
52        66
53    }
54}
55
56impl StartCommand {
57    fn start_server_async(&self, ctx: &ServerContext, identifier: &str) -> Result<String> {
58        let server_info = {
59            let servers = ctx.servers.read().unwrap();
60            find_server(&servers, identifier)?.clone()
61        };
62
63        if server_info.status == ServerStatus::Running {
64            return Ok(format!("Server '{}' läuft bereits!", server_info.name));
65        }
66
67        if !is_port_available(server_info.port) {
68            return Ok(format!("Port {} bereits belegt!", server_info.port));
69        }
70
71        match self.spawn_server(ctx, server_info.clone()) {
72            Ok(handle) => {
73                {
74                    let mut handles = ctx.handles.write().unwrap();
75                    handles.insert(server_info.id.clone(), handle);
76                }
77                self.update_server_status(ctx, &server_info.id, ServerStatus::Running);
78                Ok(format!(
79                    "Server '{}' erfolgreich gestartet auf http://127.0.0.1:{}",
80                    server_info.name, server_info.port
81                ))
82            }
83            Err(e) => {
84                self.update_server_status(ctx, &server_info.id, ServerStatus::Failed);
85                Err(AppError::Validation(format!(
86                    "Server-Start fehlgeschlagen: {}",
87                    e
88                )))
89            }
90        }
91    }
92
93    fn spawn_server(
94        &self,
95        ctx: &ServerContext,
96        server_info: crate::server::types::ServerInfo,
97    ) -> std::result::Result<actix_web::dev::ServerHandle, String> {
98        create_web_server(ctx, server_info)
99    }
100
101    fn update_server_status(&self, ctx: &ServerContext, server_id: &str, status: ServerStatus) {
102        if let Ok(mut servers) = ctx.servers.write() {
103            if let Some(server) = servers.get_mut(server_id) {
104                server.status = status;
105            }
106        }
107    }
108}