forge_core/daemon/
traits.rs1use std::future::Future;
2use std::pin::Pin;
3use std::str::FromStr;
4use std::time::Duration;
5
6use crate::error::Result;
7
8use super::context::DaemonContext;
9
10pub trait ForgeDaemon: Send + Sync + 'static {
16 fn info() -> DaemonInfo;
18
19 fn execute(ctx: &DaemonContext) -> Pin<Box<dyn Future<Output = Result<()>> + Send + '_>>;
34}
35
36#[derive(Debug, Clone)]
38pub struct DaemonInfo {
39 pub name: &'static str,
41 pub leader_elected: bool,
43 pub restart_on_panic: bool,
45 pub restart_delay: Duration,
47 pub startup_delay: Duration,
49 pub http_timeout: Option<Duration>,
51 pub max_restarts: Option<u32>,
53}
54
55impl Default for DaemonInfo {
56 fn default() -> Self {
57 Self {
58 name: "",
59 leader_elected: true,
60 restart_on_panic: true,
61 restart_delay: Duration::from_secs(5),
62 startup_delay: Duration::from_secs(0),
63 http_timeout: None,
64 max_restarts: None,
65 }
66 }
67}
68
69#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum DaemonStatus {
72 Pending,
74 Acquiring,
76 Running,
78 Stopped,
80 Failed,
82 Restarting,
84}
85
86impl DaemonStatus {
87 pub fn as_str(&self) -> &'static str {
89 match self {
90 Self::Pending => "pending",
91 Self::Acquiring => "acquiring",
92 Self::Running => "running",
93 Self::Stopped => "stopped",
94 Self::Failed => "failed",
95 Self::Restarting => "restarting",
96 }
97 }
98}
99
100impl FromStr for DaemonStatus {
101 type Err = std::convert::Infallible;
102
103 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
104 Ok(match s {
105 "pending" => Self::Pending,
106 "acquiring" => Self::Acquiring,
107 "running" => Self::Running,
108 "stopped" => Self::Stopped,
109 "failed" => Self::Failed,
110 "restarting" => Self::Restarting,
111 _ => Self::Pending,
112 })
113 }
114}
115
116#[cfg(test)]
117#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_default_daemon_info() {
123 let info = DaemonInfo::default();
124 assert!(info.leader_elected);
125 assert!(info.restart_on_panic);
126 assert_eq!(info.restart_delay, Duration::from_secs(5));
127 assert_eq!(info.startup_delay, Duration::from_secs(0));
128 assert_eq!(info.http_timeout, None);
129 assert!(info.max_restarts.is_none());
130 }
131
132 #[test]
133 fn test_status_conversion() {
134 assert_eq!(DaemonStatus::Running.as_str(), "running");
135 assert_eq!("running".parse::<DaemonStatus>(), Ok(DaemonStatus::Running));
136 assert_eq!(DaemonStatus::Failed.as_str(), "failed");
137 assert_eq!("failed".parse::<DaemonStatus>(), Ok(DaemonStatus::Failed));
138 }
139}