mecha10_cli/services/process/control.rs
1//! Status, stop/restart, and cleanup operations for `ProcessService`
2
3use super::ProcessService;
4use anyhow::Result;
5use std::collections::HashMap;
6
7impl ProcessService {
8 /// Get status of all processes
9 ///
10 /// Returns a HashMap mapping process names to status strings
11 pub fn get_status(&mut self) -> HashMap<String, String> {
12 use mecha10_runtime::ProcessStatus;
13
14 self.manager
15 .status_all()
16 .into_iter()
17 .map(|(name, status)| {
18 let status_str = match status {
19 ProcessStatus::Running => "running".to_string(),
20 ProcessStatus::Exited(code) => format!("exited (code: {})", code),
21 ProcessStatus::Error => "error".to_string(),
22 };
23 (name, status_str)
24 })
25 .collect()
26 }
27
28 /// Stop a specific process by name
29 ///
30 /// # Arguments
31 ///
32 /// * `name` - Name of the process to stop
33 ///
34 /// # Errors
35 ///
36 /// Returns an error if the process is not found
37 ///
38 /// Note: This uses a default 10-second timeout for graceful shutdown.
39 /// Use stop_with_timeout() for custom timeout.
40 pub fn stop(&mut self, name: &str) -> Result<()> {
41 self.manager.stop_graceful(name, std::time::Duration::from_secs(10))
42 }
43
44 /// Stop a process with timeout for graceful shutdown
45 ///
46 /// Tries graceful shutdown (SIGTERM on Unix), then force kills after timeout
47 ///
48 /// # Arguments
49 ///
50 /// * `name` - Name of the process to stop
51 /// * `timeout` - How long to wait for graceful shutdown
52 ///
53 /// # Errors
54 ///
55 /// Returns an error if process not found or cannot be stopped
56 pub fn stop_with_timeout(&mut self, name: &str, timeout: std::time::Duration) -> Result<()> {
57 self.manager.stop_graceful(name, timeout)
58 }
59
60 /// Force kill a process by name
61 ///
62 /// # Arguments
63 ///
64 /// * `name` - Name of the process to kill
65 pub fn force_kill(&mut self, name: &str) -> Result<()> {
66 self.manager.force_kill(name)
67 }
68
69 /// Stop all processes gracefully in dependency order
70 ///
71 /// This delegates to the runtime's ProcessManager which handles:
72 /// - Dependency-based shutdown ordering
73 /// - Graceful shutdown with timeout
74 /// - Force kill fallback
75 pub fn cleanup(&mut self) {
76 self.manager.shutdown_all();
77 }
78
79 /// Check if a process is running
80 ///
81 /// # Arguments
82 ///
83 /// * `name` - Name of the process to check
84 pub fn is_running(&mut self, name: &str) -> bool {
85 self.manager.is_running(name)
86 }
87
88 /// Restart a specific process
89 ///
90 /// Stops the process if running and starts it again
91 ///
92 /// # Arguments
93 ///
94 /// * `name` - Name of the process
95 /// * `binary_path` - Path to the binary
96 /// * `args` - Command-line arguments
97 pub fn restart(&mut self, name: &str, binary_path: &str, args: &[&str]) -> Result<u32> {
98 // Stop if running
99 if self.is_running(name) {
100 self.stop(name)?;
101 // Give it a moment to shutdown
102 std::thread::sleep(std::time::Duration::from_millis(100));
103 }
104
105 // Start again
106 self.spawn_node(name, binary_path, args)
107 }
108
109 /// Restart all processes
110 ///
111 /// # Arguments
112 ///
113 /// * `nodes` - Vec of (name, binary_path, args) tuples
114 pub fn restart_all(&mut self, nodes: Vec<(&str, &str, Vec<&str>)>) -> Result<HashMap<String, u32>> {
115 // Stop all
116 self.cleanup();
117
118 // Small delay for cleanup
119 std::thread::sleep(std::time::Duration::from_millis(500));
120
121 // Start all
122 self.spawn_nodes(nodes)
123 }
124}