1use std::sync::{Arc, Mutex};
6use log::{info, error};
7use crate::error::DaemonError;
8use crate::config::DaemonConfig;
9use crate::binary::BinaryManager;
10
11#[derive(Debug, Clone, Copy, PartialEq)]
13pub enum DaemonState {
14 Offline,
15 Booting,
16 Loading,
17 Running,
18 Restarting,
19 Closing,
20 Errored,
21}
22
23pub struct Daemon {
25 state: Arc<Mutex<DaemonState>>,
26 binary_manager: Option<BinaryManager>,
27}
28
29impl Daemon {
30 pub fn new() -> Self {
32 Daemon {
33 state: Arc::new(Mutex::new(DaemonState::Offline)),
34 binary_manager: None,
35 }
36 }
37
38 pub fn get_state(&self) -> DaemonState {
40 *self.state.lock().unwrap()
41 }
42
43 pub fn start(&self, on_start: impl FnOnce() -> Result<(), DaemonError>) -> Result<(), DaemonError> {
45 let mut state = self.state.lock().unwrap();
46 if *state == DaemonState::Running {
47 return Err(DaemonError::AlreadyRunning);
48 }
49
50 *state = DaemonState::Booting;
51 info!("Daemon is booting...");
52
53 match on_start() {
54 Ok(_) => {
55 *state = DaemonState::Running;
56 info!("Daemon is running.");
57 Ok(())
58 }
59 Err(e) => {
60 *state = DaemonState::Errored;
61 error!("Failed to start daemon: {}", e);
62 Err(e)
63 }
64 }
65 }
66
67 pub fn stop(&self, on_stop: impl FnOnce() -> Result<(), DaemonError>) -> Result<(), DaemonError> {
69 let mut state = self.state.lock().unwrap();
70 if *state != DaemonState::Running {
71 return Err(DaemonError::NotRunning);
72 }
73
74 *state = DaemonState::Closing;
75 info!("Daemon is closing...");
76
77 match on_stop() {
78 Ok(_) => {
79 *state = DaemonState::Offline;
80 info!("Daemon stopped successfully.");
81 Ok(())
82 }
83 Err(e) => {
84 *state = DaemonState::Errored;
85 error!("Failed to stop daemon: {}", e);
86 Err(e)
87 }
88 }
89 }
90
91 pub fn restart(&self, on_restart: impl Fn() -> Result<(), DaemonError> + Clone) -> Result<(), DaemonError> {
93 self.stop(on_restart.clone())?;
94 self.start(on_restart)
95 }
96
97 pub fn load_config(&mut self, config: &DaemonConfig) -> Result<(), DaemonError> {
99 log::set_max_level(match config.log_level.as_str() {
101 "debug" => log::LevelFilter::Debug,
102 "info" => log::LevelFilter::Info,
103 "warn" => log::LevelFilter::Warn,
104 "error" => log::LevelFilter::Error,
105 _ => log::LevelFilter::Info,
106 });
107
108 let binary_manager = BinaryManager::new(config.binary_paths.clone());
110 binary_manager.load_all()?;
111 self.binary_manager = Some(binary_manager);
112
113 Ok(())
114 }
115
116 #[cfg(feature = "async")]
118 pub async fn start_async<F, Fut>(&self, on_start: F) -> Result<(), DaemonError>
119 where
120 F: FnOnce() -> Fut,
121 Fut: std::future::Future<Output = Result<(), DaemonError>>,
122 {
123 let mut state = self.state.lock().unwrap();
124 if *state == DaemonState::Running {
125 return Err(DaemonError::AlreadyRunning);
126 }
127
128 *state = DaemonState::Booting;
129 info!("Daemon is booting...");
130
131 match on_start().await {
132 Ok(_) => {
133 *state = DaemonState::Running;
134 info!("Daemon is running.");
135 Ok(())
136 }
137 Err(e) => {
138 *state = DaemonState::Errored;
139 error!("Failed to start daemon: {}", e);
140 Err(e)
141 }
142 }
143 }
144
145 #[cfg(feature = "async")]
147 pub async fn stop_async<F, Fut>(&self, on_stop: F) -> Result<(), DaemonError>
148 where
149 F: FnOnce() -> Fut,
150 Fut: std::future::Future<Output = Result<(), DaemonError>>,
151 {
152 let mut state = self.state.lock().unwrap();
153 if *state != DaemonState::Running {
154 return Err(DaemonError::NotRunning);
155 }
156
157 *state = DaemonState::Closing;
158 info!("Daemon is closing...");
159
160 match on_stop().await {
161 Ok(_) => {
162 *state = DaemonState::Offline;
163 info!("Daemon stopped successfully.");
164 Ok(())
165 }
166 Err(e) => {
167 *state = DaemonState::Errored;
168 error!("Failed to stop daemon: {}", e);
169 Err(e)
170 }
171 }
172 }
173}