daemon_base/
core.rs

1//! Core functionality for the daemon library.
2//!
3//! This module defines the `Daemon` struct, which manages the daemon's state and lifecycle.
4
5use std::sync::{Arc, Mutex};
6use log::{info, error};
7use crate::error::DaemonError;
8use crate::config::DaemonConfig;
9use crate::binary::BinaryManager;
10
11/// Represents the state of the daemon.
12#[derive(Debug, Clone, Copy, PartialEq)]
13pub enum DaemonState {
14    Offline,
15    Booting,
16    Loading,
17    Running,
18    Restarting,
19    Closing,
20    Errored,
21}
22
23/// The main daemon struct.
24pub struct Daemon {
25    state: Arc<Mutex<DaemonState>>,
26    binary_manager: Option<BinaryManager>,
27}
28
29impl Daemon {
30    /// Creates a new daemon instance.
31    pub fn new() -> Self {
32        Daemon {
33            state: Arc::new(Mutex::new(DaemonState::Offline)),
34            binary_manager: None,
35        }
36    }
37
38    /// Returns the current state of the daemon.
39    pub fn get_state(&self) -> DaemonState {
40        *self.state.lock().unwrap()
41    }
42
43    /// Starts the daemon with a synchronous callback.
44    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    /// Stops the daemon with a synchronous callback.
68    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    /// Restarts the daemon with a synchronous callback.
92    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    /// Loads configuration into the daemon.
98    pub fn load_config(&mut self, config: &DaemonConfig) -> Result<(), DaemonError> {
99        // Set log level based on config
100        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        // Load binaries
109        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    /// Starts the daemon with an asynchronous callback (requires `async` feature).
117    #[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    /// Stops the daemon with an asynchronous callback (requires `async` feature).
146    #[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}