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 }
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}