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 max_restarts: Option<u32>,
51}
52
53impl Default for DaemonInfo {
54 fn default() -> Self {
55 Self {
56 name: "",
57 leader_elected: true,
58 restart_on_panic: true,
59 restart_delay: Duration::from_secs(5),
60 startup_delay: Duration::from_secs(0),
61 max_restarts: None,
62 }
63 }
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
68pub enum DaemonStatus {
69 Pending,
71 Acquiring,
73 Running,
75 Stopped,
77 Failed,
79 Restarting,
81}
82
83impl DaemonStatus {
84 pub fn as_str(&self) -> &'static str {
86 match self {
87 Self::Pending => "pending",
88 Self::Acquiring => "acquiring",
89 Self::Running => "running",
90 Self::Stopped => "stopped",
91 Self::Failed => "failed",
92 Self::Restarting => "restarting",
93 }
94 }
95}
96
97impl FromStr for DaemonStatus {
98 type Err = std::convert::Infallible;
99
100 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
101 Ok(match s {
102 "pending" => Self::Pending,
103 "acquiring" => Self::Acquiring,
104 "running" => Self::Running,
105 "stopped" => Self::Stopped,
106 "failed" => Self::Failed,
107 "restarting" => Self::Restarting,
108 _ => Self::Pending,
109 })
110 }
111}
112
113#[cfg(test)]
114#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_default_daemon_info() {
120 let info = DaemonInfo::default();
121 assert!(info.leader_elected);
122 assert!(info.restart_on_panic);
123 assert_eq!(info.restart_delay, Duration::from_secs(5));
124 assert_eq!(info.startup_delay, Duration::from_secs(0));
125 assert!(info.max_restarts.is_none());
126 }
127
128 #[test]
129 fn test_status_conversion() {
130 assert_eq!(DaemonStatus::Running.as_str(), "running");
131 assert_eq!("running".parse::<DaemonStatus>(), Ok(DaemonStatus::Running));
132 assert_eq!(DaemonStatus::Failed.as_str(), "failed");
133 assert_eq!("failed".parse::<DaemonStatus>(), Ok(DaemonStatus::Failed));
134 }
135}