rust_supervisor/spec/supervisor_builder.rs
1//! Builder for [`SupervisorSpec`].
2//!
3//! Use this module when constructing supervisor specifications in code. The
4//! builder mirrors [`SupervisorSpec::root`](crate::spec::supervisor::SupervisorSpec::root)
5//! defaults, then lets callers override policy, topology, and runtime settings
6//! through a fluent API.
7
8use crate::error::types::SupervisorError;
9use crate::id::types::SupervisorPath;
10use crate::policy::budget::RestartBudgetConfig;
11use crate::policy::failure_window::FailureWindowConfig;
12use crate::policy::group::GroupDependencyEdge;
13use crate::policy::meltdown::MeltdownPolicy;
14use crate::policy::task_role_defaults::{SeverityClass, TaskRole};
15use crate::spec::child::{BackoffPolicy, ChildSpec, HealthPolicy, RestartPolicy};
16use crate::spec::shutdown::TreeShutdownPolicy;
17use crate::spec::supervisor::{
18 BackpressureConfig, ChildStrategyOverride, DynamicSupervisorPolicy, EscalationPolicy,
19 GroupConfig, GroupStrategy, RestartLimit, SupervisionStrategy, SupervisorSpec,
20};
21use std::collections::HashMap;
22
23/// Builder for [`SupervisorSpec`].
24///
25/// Public constructors and setters keep returning [`SupervisorSpecBuilder`] for
26/// chaining. Call [`build`](SupervisorSpecBuilder::build) to consume the
27/// builder, validate local invariants, and receive the final [`SupervisorSpec`].
28#[derive(Debug, Clone)]
29pub struct SupervisorSpecBuilder {
30 /// Supervisor specification under construction.
31 spec: SupervisorSpec,
32}
33
34impl SupervisorSpecBuilder {
35 /// Creates a root supervisor specification builder.
36 ///
37 /// # Arguments
38 ///
39 /// - `children`: Children declared under the root supervisor.
40 ///
41 /// # Returns
42 ///
43 /// Returns a builder seeded with the same defaults as [`SupervisorSpec::root`].
44 ///
45 /// # Examples
46 ///
47 /// ```
48 /// use rust_supervisor::spec::supervisor_builder::SupervisorSpecBuilder;
49 ///
50 /// # fn example() -> Result<(), rust_supervisor::error::types::SupervisorError> {
51 /// let spec = SupervisorSpecBuilder::root(Vec::new()).build()?;
52 /// assert_eq!(spec.path.to_string(), "/");
53 /// # Ok(())
54 /// # }
55 /// ```
56 pub fn root(children: Vec<ChildSpec>) -> Self {
57 Self {
58 spec: SupervisorSpec::root(children),
59 }
60 }
61
62 /// Creates a root supervisor specification builder.
63 ///
64 /// # Arguments
65 ///
66 /// - `children`: Children declared under the root supervisor.
67 ///
68 /// # Returns
69 ///
70 /// Returns a builder seeded with the same defaults as [`SupervisorSpec::root`].
71 pub fn new(children: Vec<ChildSpec>) -> Self {
72 Self::root(children)
73 }
74
75 /// Sets the supervisor path.
76 ///
77 /// # Arguments
78 ///
79 /// - `path`: Stable path for this supervisor.
80 ///
81 /// # Returns
82 ///
83 /// Returns the builder for chaining.
84 pub fn path(mut self, path: SupervisorPath) -> Self {
85 self.spec.path = path;
86 self
87 }
88
89 /// Sets the restart scope strategy.
90 ///
91 /// # Arguments
92 ///
93 /// - `strategy`: Restart strategy for child exits.
94 ///
95 /// # Returns
96 ///
97 /// Returns the builder for chaining.
98 pub fn strategy(mut self, strategy: SupervisionStrategy) -> Self {
99 self.spec.strategy = strategy;
100 self
101 }
102
103 /// Replaces supervisor children.
104 ///
105 /// # Arguments
106 ///
107 /// - `children`: Children declared under the supervisor.
108 ///
109 /// # Returns
110 ///
111 /// Returns the builder for chaining.
112 pub fn children(mut self, children: Vec<ChildSpec>) -> Self {
113 self.spec.children = children;
114 self
115 }
116
117 /// Appends one supervisor child.
118 ///
119 /// # Arguments
120 ///
121 /// - `child`: Child specification appended in declaration order.
122 ///
123 /// # Returns
124 ///
125 /// Returns the builder for chaining.
126 pub fn child(mut self, mut child: ChildSpec) -> Self {
127 child.shutdown_budget = self.spec.tree_shutdown.budget;
128 self.spec.children.push(child);
129 self
130 }
131
132 /// Sets the configuration version.
133 ///
134 /// # Arguments
135 ///
136 /// - `config_version`: Version string that produced this declaration.
137 ///
138 /// # Returns
139 ///
140 /// Returns the builder for chaining.
141 pub fn config_version(mut self, config_version: impl Into<String>) -> Self {
142 self.spec.config_version = config_version.into();
143 self
144 }
145
146 /// Sets the default restart policy.
147 ///
148 /// # Arguments
149 ///
150 /// - `default_restart_policy`: Restart policy inherited by children.
151 ///
152 /// # Returns
153 ///
154 /// Returns the builder for chaining.
155 pub fn default_restart_policy(mut self, default_restart_policy: RestartPolicy) -> Self {
156 self.spec.default_restart_policy = default_restart_policy;
157 self
158 }
159
160 /// Sets the default backoff policy.
161 ///
162 /// # Arguments
163 ///
164 /// - `default_backoff_policy`: Backoff policy inherited by children.
165 ///
166 /// # Returns
167 ///
168 /// Returns the builder for chaining.
169 pub fn default_backoff_policy(mut self, default_backoff_policy: BackoffPolicy) -> Self {
170 self.spec.default_backoff_policy = default_backoff_policy;
171 self
172 }
173
174 /// Sets the default health policy.
175 ///
176 /// # Arguments
177 ///
178 /// - `default_health_policy`: Health policy inherited by children.
179 ///
180 /// # Returns
181 ///
182 /// Returns the builder for chaining.
183 pub fn default_health_policy(mut self, default_health_policy: HealthPolicy) -> Self {
184 self.spec.default_health_policy = default_health_policy;
185 self
186 }
187
188 /// Sets the tree shutdown policy for this supervisor.
189 ///
190 /// # Arguments
191 ///
192 /// - `tree_shutdown`: Tree shutdown policy and default child budgets.
193 ///
194 /// # Returns
195 ///
196 /// Returns the builder for chaining.
197 pub fn tree_shutdown(mut self, tree_shutdown: TreeShutdownPolicy) -> Self {
198 self.spec.tree_shutdown = tree_shutdown;
199 self
200 }
201
202 /// Sets the supervisor failure limit.
203 ///
204 /// # Arguments
205 ///
206 /// - `supervisor_failure_limit`: Maximum supervisor failures before escalation.
207 ///
208 /// # Returns
209 ///
210 /// Returns the builder for chaining.
211 pub fn supervisor_failure_limit(mut self, supervisor_failure_limit: u32) -> Self {
212 self.spec.supervisor_failure_limit = supervisor_failure_limit;
213 self
214 }
215
216 /// Sets the supervisor-level restart limit.
217 ///
218 /// # Arguments
219 ///
220 /// - `restart_limit`: Restart limit applied at supervisor level.
221 ///
222 /// # Returns
223 ///
224 /// Returns the builder for chaining.
225 pub fn restart_limit(mut self, restart_limit: RestartLimit) -> Self {
226 self.spec.restart_limit = Some(restart_limit);
227 self
228 }
229
230 /// Clears the supervisor-level restart limit.
231 ///
232 /// # Arguments
233 ///
234 /// This function has no arguments.
235 ///
236 /// # Returns
237 ///
238 /// Returns the builder for chaining.
239 pub fn without_restart_limit(mut self) -> Self {
240 self.spec.restart_limit = None;
241 self
242 }
243
244 /// Sets the supervisor-level fallback escalation policy.
245 ///
246 /// The selected policy is used when a child-level or group-level execution
247 /// plan does not define its own escalation policy. Root supervisors do not
248 /// have a parent supervisor at runtime, so `EscalateToParent` is only a
249 /// configured planning and diagnostic label for root supervisors.
250 ///
251 /// # Arguments
252 ///
253 /// - `escalation_policy`: Fallback escalation policy applied at supervisor level.
254 ///
255 /// # Returns
256 ///
257 /// Returns the builder for chaining.
258 pub fn escalation_policy(mut self, escalation_policy: EscalationPolicy) -> Self {
259 self.spec.escalation_policy = Some(escalation_policy);
260 self
261 }
262
263 /// Clears the supervisor-level fallback escalation policy.
264 ///
265 /// # Arguments
266 ///
267 /// This function has no arguments.
268 ///
269 /// # Returns
270 ///
271 /// Returns the builder for chaining.
272 pub fn without_escalation_policy(mut self) -> Self {
273 self.spec.escalation_policy = None;
274 self
275 }
276
277 /// Replaces group strategy overrides.
278 ///
279 /// # Arguments
280 ///
281 /// - `group_strategies`: Group strategy overrides.
282 ///
283 /// # Returns
284 ///
285 /// Returns the builder for chaining.
286 pub fn group_strategies(mut self, group_strategies: Vec<GroupStrategy>) -> Self {
287 self.spec.group_strategies = group_strategies;
288 self
289 }
290
291 /// Appends one group strategy override.
292 ///
293 /// # Arguments
294 ///
295 /// - `group_strategy`: Group strategy override appended to the supervisor.
296 ///
297 /// # Returns
298 ///
299 /// Returns the builder for chaining.
300 pub fn group_strategy(mut self, group_strategy: GroupStrategy) -> Self {
301 self.spec.group_strategies.push(group_strategy);
302 self
303 }
304
305 /// Replaces group configurations.
306 ///
307 /// # Arguments
308 ///
309 /// - `group_configs`: Group-level membership and budget configurations.
310 ///
311 /// # Returns
312 ///
313 /// Returns the builder for chaining.
314 pub fn group_configs(mut self, group_configs: Vec<GroupConfig>) -> Self {
315 self.spec.group_configs = group_configs;
316 self
317 }
318
319 /// Appends one group configuration.
320 ///
321 /// # Arguments
322 ///
323 /// - `group_config`: Group configuration appended to the supervisor.
324 ///
325 /// # Returns
326 ///
327 /// Returns the builder for chaining.
328 pub fn group_config(mut self, group_config: GroupConfig) -> Self {
329 self.spec.group_configs.push(group_config);
330 self
331 }
332
333 /// Replaces cross-group dependency edges.
334 ///
335 /// # Arguments
336 ///
337 /// - `group_dependencies`: Cross-group dependency edges.
338 ///
339 /// # Returns
340 ///
341 /// Returns the builder for chaining.
342 pub fn group_dependencies(mut self, group_dependencies: Vec<GroupDependencyEdge>) -> Self {
343 self.spec.group_dependencies = group_dependencies;
344 self
345 }
346
347 /// Appends one cross-group dependency edge.
348 ///
349 /// # Arguments
350 ///
351 /// - `group_dependency`: Cross-group dependency edge appended to the supervisor.
352 ///
353 /// # Returns
354 ///
355 /// Returns the builder for chaining.
356 pub fn group_dependency(mut self, group_dependency: GroupDependencyEdge) -> Self {
357 self.spec.group_dependencies.push(group_dependency);
358 self
359 }
360
361 /// Replaces default severity classes by task role.
362 ///
363 /// # Arguments
364 ///
365 /// - `severity_defaults`: Default severity map by task role.
366 ///
367 /// # Returns
368 ///
369 /// Returns the builder for chaining.
370 pub fn severity_defaults(
371 mut self,
372 severity_defaults: HashMap<TaskRole, SeverityClass>,
373 ) -> Self {
374 self.spec.severity_defaults = severity_defaults;
375 self
376 }
377
378 /// Sets one default severity class.
379 ///
380 /// # Arguments
381 ///
382 /// - `task_role`: Task role receiving the default severity class.
383 /// - `severity`: Severity class used for the task role.
384 ///
385 /// # Returns
386 ///
387 /// Returns the builder for chaining.
388 pub fn severity_default(mut self, task_role: TaskRole, severity: SeverityClass) -> Self {
389 self.spec.severity_defaults.insert(task_role, severity);
390 self
391 }
392
393 /// Removes one default severity class.
394 ///
395 /// # Arguments
396 ///
397 /// - `task_role`: Task role whose default severity class is removed.
398 ///
399 /// # Returns
400 ///
401 /// Returns the builder for chaining.
402 pub fn without_severity_default(mut self, task_role: TaskRole) -> Self {
403 self.spec.severity_defaults.remove(&task_role);
404 self
405 }
406
407 /// Replaces child-level strategy overrides.
408 ///
409 /// # Arguments
410 ///
411 /// - `child_strategy_overrides`: Child-level strategy overrides.
412 ///
413 /// # Returns
414 ///
415 /// Returns the builder for chaining.
416 pub fn child_strategy_overrides(
417 mut self,
418 child_strategy_overrides: Vec<ChildStrategyOverride>,
419 ) -> Self {
420 self.spec.child_strategy_overrides = child_strategy_overrides;
421 self
422 }
423
424 /// Appends one child-level strategy override.
425 ///
426 /// # Arguments
427 ///
428 /// - `child_strategy_override`: Child-level strategy override appended to the supervisor.
429 ///
430 /// # Returns
431 ///
432 /// Returns the builder for chaining.
433 pub fn child_strategy_override(
434 mut self,
435 child_strategy_override: ChildStrategyOverride,
436 ) -> Self {
437 self.spec
438 .child_strategy_overrides
439 .push(child_strategy_override);
440 self
441 }
442
443 /// Sets the dynamic supervisor policy.
444 ///
445 /// # Arguments
446 ///
447 /// - `dynamic_supervisor_policy`: Runtime child addition policy.
448 ///
449 /// # Returns
450 ///
451 /// Returns the builder for chaining.
452 pub fn dynamic_supervisor_policy(
453 mut self,
454 dynamic_supervisor_policy: DynamicSupervisorPolicy,
455 ) -> Self {
456 self.spec.dynamic_supervisor_policy = dynamic_supervisor_policy;
457 self
458 }
459
460 /// Sets the control command channel capacity.
461 ///
462 /// # Arguments
463 ///
464 /// - `control_channel_capacity`: Control command channel capacity.
465 ///
466 /// # Returns
467 ///
468 /// Returns the builder for chaining.
469 pub fn control_channel_capacity(mut self, control_channel_capacity: usize) -> Self {
470 self.spec.control_channel_capacity = control_channel_capacity;
471 self
472 }
473
474 /// Sets the event broadcast channel capacity.
475 ///
476 /// # Arguments
477 ///
478 /// - `event_channel_capacity`: Event broadcast channel capacity.
479 ///
480 /// # Returns
481 ///
482 /// Returns the builder for chaining.
483 pub fn event_channel_capacity(mut self, event_channel_capacity: usize) -> Self {
484 self.spec.event_channel_capacity = event_channel_capacity;
485 self
486 }
487
488 /// Sets the backpressure configuration.
489 ///
490 /// # Arguments
491 ///
492 /// - `backpressure_config`: Backpressure configuration for event subscribers.
493 ///
494 /// # Returns
495 ///
496 /// Returns the builder for chaining.
497 pub fn backpressure_config(mut self, backpressure_config: BackpressureConfig) -> Self {
498 self.spec.backpressure_config = backpressure_config;
499 self
500 }
501
502 /// Sets the meltdown policy.
503 ///
504 /// # Arguments
505 ///
506 /// - `meltdown_policy`: Failure fuse policy.
507 ///
508 /// # Returns
509 ///
510 /// Returns the builder for chaining.
511 pub fn meltdown_policy(mut self, meltdown_policy: MeltdownPolicy) -> Self {
512 self.spec.meltdown_policy = meltdown_policy;
513 self
514 }
515
516 /// Sets the failure window configuration.
517 ///
518 /// # Arguments
519 ///
520 /// - `failure_window_config`: Failure accumulation window configuration.
521 ///
522 /// # Returns
523 ///
524 /// Returns the builder for chaining.
525 pub fn failure_window_config(mut self, failure_window_config: FailureWindowConfig) -> Self {
526 self.spec.failure_window_config = failure_window_config;
527 self
528 }
529
530 /// Sets the restart budget configuration.
531 ///
532 /// # Arguments
533 ///
534 /// - `restart_budget_config`: Restart budget configuration.
535 ///
536 /// # Returns
537 ///
538 /// Returns the builder for chaining.
539 pub fn restart_budget_config(mut self, restart_budget_config: RestartBudgetConfig) -> Self {
540 self.spec.restart_budget_config = restart_budget_config;
541 self
542 }
543
544 /// Sets the event journal capacity used by the supervision pipeline.
545 ///
546 /// # Arguments
547 ///
548 /// - `pipeline_journal_capacity`: Event journal capacity.
549 ///
550 /// # Returns
551 ///
552 /// Returns the builder for chaining.
553 pub fn pipeline_journal_capacity(mut self, pipeline_journal_capacity: usize) -> Self {
554 self.spec.pipeline_journal_capacity = pipeline_journal_capacity;
555 self
556 }
557
558 /// Sets the subscriber queue capacity used by the supervision pipeline.
559 ///
560 /// # Arguments
561 ///
562 /// - `pipeline_subscriber_capacity`: Subscriber queue capacity.
563 ///
564 /// # Returns
565 ///
566 /// Returns the builder for chaining.
567 pub fn pipeline_subscriber_capacity(mut self, pipeline_subscriber_capacity: usize) -> Self {
568 self.spec.pipeline_subscriber_capacity = pipeline_subscriber_capacity;
569 self
570 }
571
572 /// Sets the concurrent restart limit.
573 ///
574 /// # Arguments
575 ///
576 /// - `concurrent_restart_limit`: Maximum concurrent restarts for this supervisor.
577 ///
578 /// # Returns
579 ///
580 /// Returns the builder for chaining.
581 pub fn concurrent_restart_limit(mut self, concurrent_restart_limit: u32) -> Self {
582 self.spec.concurrent_restart_limit = concurrent_restart_limit;
583 self
584 }
585
586 /// Sets whether metrics recording is enabled.
587 ///
588 /// # Arguments
589 ///
590 /// - `metrics_enabled`: Whether metrics recording is enabled.
591 ///
592 /// # Returns
593 ///
594 /// Returns the builder for chaining.
595 pub fn metrics_enabled(mut self, metrics_enabled: bool) -> Self {
596 self.spec.metrics_enabled = metrics_enabled;
597 self
598 }
599
600 /// Sets whether audit event recording is enabled.
601 ///
602 /// # Arguments
603 ///
604 /// - `audit_enabled`: Whether audit event recording is enabled.
605 ///
606 /// # Returns
607 ///
608 /// Returns the builder for chaining.
609 pub fn audit_enabled(mut self, audit_enabled: bool) -> Self {
610 self.spec.audit_enabled = audit_enabled;
611 self
612 }
613 /// Builds and validates the supervisor specification.
614 ///
615 /// # Arguments
616 ///
617 /// This function has no arguments.
618 ///
619 /// # Returns
620 ///
621 /// Returns the constructed [`SupervisorSpec`] when local invariants pass.
622 ///
623 /// # Errors
624 ///
625 /// Returns [`SupervisorError`] when validation fails.
626 ///
627 /// # Examples
628 ///
629 /// ```
630 /// use rust_supervisor::spec::supervisor_builder::SupervisorSpecBuilder;
631 ///
632 /// # fn example() -> Result<(), rust_supervisor::error::types::SupervisorError> {
633 /// let spec = SupervisorSpecBuilder::root(Vec::new())
634 /// .config_version("demo")
635 /// .build()?;
636 /// assert_eq!(spec.config_version, "demo");
637 /// # Ok(())
638 /// # }
639 /// ```
640 ///
641 /// ```compile_fail
642 /// use rust_supervisor::spec::supervisor::SupervisorSpec;
643 /// use rust_supervisor::spec::supervisor_builder::SupervisorSpecBuilder;
644 ///
645 /// let builder = SupervisorSpecBuilder::root(Vec::new());
646 /// let _spec: SupervisorSpec = builder;
647 /// ```
648 pub fn build(self) -> Result<SupervisorSpec, SupervisorError> {
649 let spec = self.spec;
650 spec.validate()?;
651 Ok(spec)
652 }
653}