Skip to main content

syspulse_core/
daemon.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::path::PathBuf;
5use uuid::Uuid;
6
7use crate::lifecycle::LifecycleState;
8use crate::resources::ResourceLimits;
9use crate::restart::RestartPolicy;
10
11fn default_interval() -> u64 {
12    30
13}
14
15fn default_timeout() -> u64 {
16    5
17}
18
19fn default_retries() -> u32 {
20    3
21}
22
23fn default_max_size() -> u64 {
24    50 * 1024 * 1024 // 50 MB
25}
26
27fn default_retain() -> u32 {
28    5
29}
30
31fn default_stop_timeout() -> u64 {
32    30
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub struct HealthCheckSpec {
37    #[serde(rename = "type")]
38    pub check_type: HealthCheckType,
39    pub target: String,
40    #[serde(default = "default_interval")]
41    pub interval_secs: u64,
42    #[serde(default = "default_timeout")]
43    pub timeout_secs: u64,
44    #[serde(default = "default_retries")]
45    pub retries: u32,
46    #[serde(default)]
47    pub start_period_secs: u64,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(rename_all = "snake_case")]
52pub enum HealthCheckType {
53    Http,
54    Tcp,
55    Command,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct LogConfig {
60    #[serde(default = "default_max_size")]
61    pub max_size_bytes: u64,
62    #[serde(default = "default_retain")]
63    pub retain_count: u32,
64    #[serde(default)]
65    pub compress_rotated: bool,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct DaemonSpec {
70    pub name: String,
71    pub command: Vec<String>,
72    #[serde(default)]
73    pub working_dir: Option<PathBuf>,
74    #[serde(default)]
75    pub env: HashMap<String, String>,
76    #[serde(default)]
77    pub health_check: Option<HealthCheckSpec>,
78    #[serde(default)]
79    pub restart_policy: RestartPolicy,
80    #[serde(default)]
81    pub resource_limits: Option<ResourceLimits>,
82    #[serde(default)]
83    pub schedule: Option<String>,
84    #[serde(default)]
85    pub tags: Vec<String>,
86    #[serde(default = "default_stop_timeout")]
87    pub stop_timeout_secs: u64,
88    #[serde(default)]
89    pub log_config: Option<LogConfig>,
90    #[serde(default)]
91    pub description: Option<String>,
92    #[serde(default)]
93    pub user: Option<String>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct DaemonInstance {
98    pub id: String,
99    pub spec_name: String,
100    pub state: LifecycleState,
101    pub pid: Option<u32>,
102    pub started_at: Option<DateTime<Utc>>,
103    pub stopped_at: Option<DateTime<Utc>>,
104    pub exit_code: Option<i32>,
105    pub restart_count: u32,
106    pub health_status: HealthStatus,
107    pub stdout_log: Option<PathBuf>,
108    pub stderr_log: Option<PathBuf>,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
112#[serde(rename_all = "snake_case")]
113pub enum HealthStatus {
114    Unknown,
115    Healthy,
116    Unhealthy,
117    NotConfigured,
118}
119
120impl DaemonInstance {
121    pub fn new(spec_name: &str) -> Self {
122        Self {
123            id: Uuid::new_v4().to_string(),
124            spec_name: spec_name.to_string(),
125            state: LifecycleState::Stopped,
126            pid: None,
127            started_at: None,
128            stopped_at: None,
129            exit_code: None,
130            restart_count: 0,
131            health_status: HealthStatus::Unknown,
132            stdout_log: None,
133            stderr_log: None,
134        }
135    }
136}