ralph/contracts/config/
parallel.rs1use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11use std::path::PathBuf;
12
13#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
15#[serde(default, deny_unknown_fields)]
16pub struct ParallelConfig {
17 #[schemars(range(min = 2))]
19 pub workers: Option<u8>,
20
21 pub workspace_root: Option<PathBuf>,
23
24 #[schemars(range(min = 1))]
26 pub max_push_attempts: Option<u8>,
27
28 pub push_backoff_ms: Option<Vec<u64>>,
30
31 #[schemars(range(min = 1))]
33 pub workspace_retention_hours: Option<u32>,
34}
35
36impl ParallelConfig {
37 pub fn merge_from(&mut self, other: Self) {
38 if other.workers.is_some() {
39 self.workers = other.workers;
40 }
41 if other.workspace_root.is_some() {
42 self.workspace_root = other.workspace_root;
43 }
44 if other.max_push_attempts.is_some() {
45 self.max_push_attempts = other.max_push_attempts;
46 }
47 if other.push_backoff_ms.is_some() {
48 self.push_backoff_ms = other.push_backoff_ms;
49 }
50 if other.workspace_retention_hours.is_some() {
51 self.workspace_retention_hours = other.workspace_retention_hours;
52 }
53 }
54}
55
56pub fn default_push_backoff_ms() -> Vec<u64> {
58 vec![500, 2000, 5000, 10000]
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn parallel_config_merge_prefers_other_when_some() {
67 let mut base = ParallelConfig {
68 workers: Some(2),
69 workspace_root: None,
70 max_push_attempts: Some(3),
71 push_backoff_ms: None,
72 workspace_retention_hours: Some(12),
73 };
74
75 let other = ParallelConfig {
76 workers: Some(4),
77 workspace_root: Some(PathBuf::from("/tmp/ws")),
78 max_push_attempts: None,
79 push_backoff_ms: Some(vec![1000, 2000]),
80 workspace_retention_hours: None,
81 };
82
83 base.merge_from(other);
84
85 assert_eq!(base.workers, Some(4));
86 assert_eq!(base.workspace_root, Some(PathBuf::from("/tmp/ws")));
87 assert_eq!(base.max_push_attempts, Some(3)); assert_eq!(base.push_backoff_ms, Some(vec![1000, 2000]));
89 assert_eq!(base.workspace_retention_hours, Some(12)); }
91
92 #[test]
93 fn default_push_backoff_ms_has_expected_values() {
94 let backoff = default_push_backoff_ms();
95 assert_eq!(backoff, vec![500, 2000, 5000, 10000]);
96 }
97}