1use confique::Config;
7use rust_config_tree::ConfigSchema;
8use schemars::JsonSchema;
9use serde::{Deserialize, Serialize};
10use std::path::PathBuf;
11
12use crate::{
13 config::{
14 audit::AuditConfig,
15 ipc_security::IpcSecurityConfig,
16 policy::{
17 ChildStrategyOverrideConfig, DynamicSupervisorConfig, FailureWindowConfig,
18 GroupDependencyConfig, GroupStrategyConfig, GroupsConfigSection, MeltdownConfig,
19 RestartBudgetConfig, SeverityDefaultConfig, SupervisionPipelineConfig,
20 },
21 },
22 spec::{
23 child_declaration::ChildrenConfigSection,
24 supervisor::{
25 BackpressureConfig, EscalationPolicy, RECOMMENDED_CHANNEL_CAPACITY, SupervisionStrategy,
26 },
27 },
28};
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema, ConfigSchema)]
32pub struct SupervisorConfig {
33 #[config(default = [])]
35 #[serde(default)]
36 pub include: Vec<PathBuf>,
37
38 #[config(nested)]
40 pub supervisor: SupervisorRootConfig,
41
42 #[config(nested)]
44 #[serde(default)]
45 pub policy: PolicyConfig,
46
47 #[config(nested)]
49 #[serde(default)]
50 pub shutdown: ShutdownConfig,
51
52 #[config(nested)]
54 #[serde(default)]
55 pub observability: ObservabilityConfig,
56
57 #[config(nested)]
59 #[serde(default)]
60 pub audit: AuditConfig,
61
62 #[config(nested)]
64 #[serde(default)]
65 pub backpressure: BackpressureConfig,
66
67 #[config(nested)]
69 #[serde(default)]
70 #[schemars(extend("x-tree-split" = true, "x-tree-transparent-array" = true))]
71 pub groups: GroupsConfigSection,
72
73 #[config(default = [])]
75 #[serde(default)]
76 pub group_strategies: Vec<GroupStrategyConfig>,
77
78 #[config(default = [])]
80 #[serde(default)]
81 pub group_dependencies: Vec<GroupDependencyConfig>,
82
83 #[config(default = [])]
85 #[serde(default)]
86 pub child_strategy_overrides: Vec<ChildStrategyOverrideConfig>,
87
88 #[config(default = [])]
90 #[serde(default)]
91 pub severity_defaults: Vec<SeverityDefaultConfig>,
92
93 pub dashboard: Option<DashboardIpcConfig>,
95
96 #[config(nested)]
98 #[serde(default)]
99 #[schemars(extend("x-tree-split" = true, "x-tree-transparent-array" = true))]
100 pub children: ChildrenConfigSection,
101}
102
103#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema)]
120pub struct SupervisorRootConfig {
121 #[config(default = "OneForAll")]
123 #[serde(default = "default_supervision_strategy")]
124 pub strategy: SupervisionStrategy,
125 #[schemars(!default)]
131 #[serde(default)]
132 pub escalation_policy: Option<EscalationPolicy>,
133 #[config(default = 256)]
138 #[serde(default = "default_channel_capacity")]
139 pub control_channel_capacity: usize,
140 #[config(default = 256)]
145 #[serde(default = "default_channel_capacity")]
146 pub event_channel_capacity: usize,
147 #[config(nested)]
149 #[serde(default)]
150 pub dynamic_supervisor: DynamicSupervisorConfig,
151}
152
153#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema)]
155pub struct PolicyConfig {
156 #[config(default = 10)]
158 #[serde(default = "default_child_restart_limit")]
159 pub child_restart_limit: u32,
160 #[config(default = 60000)]
162 #[serde(default = "default_child_restart_window_ms")]
163 pub child_restart_window_ms: u64,
164 #[config(default = 30)]
166 #[serde(default = "default_supervisor_failure_limit")]
167 pub supervisor_failure_limit: u32,
168 #[config(default = 60000)]
170 #[serde(default = "default_supervisor_failure_window_ms")]
171 pub supervisor_failure_window_ms: u64,
172 #[config(default = 100)]
174 #[serde(default = "default_initial_backoff_ms")]
175 pub initial_backoff_ms: u64,
176 #[config(default = 5000)]
178 #[serde(default = "default_max_backoff_ms")]
179 pub max_backoff_ms: u64,
180 #[config(default = 0.10)]
182 #[serde(default = "default_jitter_ratio")]
183 pub jitter_ratio: f64,
184 #[config(default = 1000)]
186 #[serde(default = "default_heartbeat_interval_ms")]
187 pub heartbeat_interval_ms: u64,
188 #[config(default = 3000)]
190 #[serde(default = "default_stale_after_ms")]
191 pub stale_after_ms: u64,
192 #[config(nested)]
194 #[serde(default)]
195 pub restart_budget: RestartBudgetConfig,
196 #[config(nested)]
198 #[serde(default)]
199 pub failure_window: FailureWindowConfig,
200 #[config(nested)]
202 #[serde(default)]
203 pub meltdown: MeltdownConfig,
204 #[config(nested)]
206 #[serde(default)]
207 pub supervision_pipeline: SupervisionPipelineConfig,
208}
209
210#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema)]
212pub struct ShutdownConfig {
213 #[config(default = 5000)]
215 #[serde(default = "default_graceful_timeout_ms")]
216 pub graceful_timeout_ms: u64,
217 #[config(default = 1000)]
219 #[serde(default = "default_abort_wait_ms")]
220 pub abort_wait_ms: u64,
221}
222
223#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema)]
225pub struct ObservabilityConfig {
226 #[config(default = 256)]
228 #[serde(default = "default_event_journal_capacity")]
229 pub event_journal_capacity: usize,
230 #[config(default = true)]
232 #[serde(default = "default_true")]
233 pub metrics_enabled: bool,
234 #[config(default = true)]
236 #[serde(default = "default_true")]
237 pub audit_enabled: bool,
238}
239
240impl Default for PolicyConfig {
241 fn default() -> Self {
243 Self {
244 child_restart_limit: default_child_restart_limit(),
245 child_restart_window_ms: default_child_restart_window_ms(),
246 supervisor_failure_limit: default_supervisor_failure_limit(),
247 supervisor_failure_window_ms: default_supervisor_failure_window_ms(),
248 initial_backoff_ms: default_initial_backoff_ms(),
249 max_backoff_ms: default_max_backoff_ms(),
250 jitter_ratio: default_jitter_ratio(),
251 heartbeat_interval_ms: default_heartbeat_interval_ms(),
252 stale_after_ms: default_stale_after_ms(),
253 restart_budget: RestartBudgetConfig::default(),
254 failure_window: FailureWindowConfig::default(),
255 meltdown: MeltdownConfig::default(),
256 supervision_pipeline: SupervisionPipelineConfig::default(),
257 }
258 }
259}
260
261impl Default for ShutdownConfig {
262 fn default() -> Self {
264 Self {
265 graceful_timeout_ms: default_graceful_timeout_ms(),
266 abort_wait_ms: default_abort_wait_ms(),
267 }
268 }
269}
270
271impl Default for ObservabilityConfig {
272 fn default() -> Self {
274 Self {
275 event_journal_capacity: default_event_journal_capacity(),
276 metrics_enabled: default_true(),
277 audit_enabled: default_true(),
278 }
279 }
280}
281
282fn default_supervision_strategy() -> SupervisionStrategy {
284 SupervisionStrategy::OneForAll
285}
286
287fn default_child_restart_limit() -> u32 {
289 10
290}
291
292fn default_child_restart_window_ms() -> u64 {
294 60000
295}
296
297fn default_supervisor_failure_limit() -> u32 {
299 30
300}
301
302fn default_supervisor_failure_window_ms() -> u64 {
304 60000
305}
306
307fn default_initial_backoff_ms() -> u64 {
309 100
310}
311
312fn default_max_backoff_ms() -> u64 {
314 5000
315}
316
317fn default_jitter_ratio() -> f64 {
319 0.10
320}
321
322fn default_heartbeat_interval_ms() -> u64 {
324 1000
325}
326
327fn default_stale_after_ms() -> u64 {
329 3000
330}
331
332fn default_graceful_timeout_ms() -> u64 {
334 5000
335}
336
337fn default_abort_wait_ms() -> u64 {
339 1000
340}
341
342fn default_channel_capacity() -> usize {
344 RECOMMENDED_CHANNEL_CAPACITY
345}
346
347fn default_event_journal_capacity() -> usize {
349 256
350}
351
352fn default_true() -> bool {
354 true
355}
356
357#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Config, JsonSchema)]
359pub struct DashboardIpcConfig {
360 pub enabled: bool,
362 pub target_id: Option<String>,
364 pub path: Option<PathBuf>,
366 pub permissions: Option<String>,
368 pub bind_mode: Option<DashboardIpcBindMode>,
370 pub registration: Option<DashboardRegistrationConfig>,
372 #[schemars(!default)]
374 #[serde(default)]
375 pub security_config: Option<IpcSecurityConfig>,
376}
377
378#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
380#[serde(rename_all = "snake_case")]
381pub enum DashboardIpcBindMode {
382 CreateNew,
384 ReplaceStale,
386}
387
388#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Config, JsonSchema)]
390pub struct DashboardRegistrationConfig {
391 pub enabled: bool,
393 pub relay_registration_path: Option<PathBuf>,
395 pub display_name: Option<String>,
397 pub lease_seconds: Option<u64>,
399 pub registration_heartbeat_interval_seconds: Option<u64>,
401 pub registration_connect_timeout_secs: Option<u64>,
404 pub registration_io_timeout_secs: Option<u64>,
407}