ruvector_dag/healing/
strategies.rs1use super::anomaly::{Anomaly, AnomalyType};
4
5#[derive(Debug, Clone)]
6pub struct RepairResult {
7 pub strategy_name: String,
8 pub success: bool,
9 pub duration_ms: f64,
10 pub details: String,
11}
12
13pub trait RepairStrategy: Send + Sync {
14 fn name(&self) -> &str;
15 fn can_repair(&self, anomaly: &Anomaly) -> bool;
16 fn repair(&self, anomaly: &Anomaly) -> RepairResult;
17}
18
19pub struct IndexRebalanceStrategy {
20 target_recall: f64,
21}
22
23impl IndexRebalanceStrategy {
24 pub fn new(target_recall: f64) -> Self {
25 Self { target_recall }
26 }
27}
28
29impl RepairStrategy for IndexRebalanceStrategy {
30 fn name(&self) -> &str {
31 "index_rebalance"
32 }
33
34 fn can_repair(&self, anomaly: &Anomaly) -> bool {
35 matches!(anomaly.anomaly_type, AnomalyType::LatencySpike)
36 }
37
38 fn repair(&self, anomaly: &Anomaly) -> RepairResult {
39 let start = std::time::Instant::now();
40
41 std::thread::sleep(std::time::Duration::from_millis(10));
44
45 RepairResult {
46 strategy_name: self.name().to_string(),
47 success: true,
48 duration_ms: start.elapsed().as_secs_f64() * 1000.0,
49 details: format!(
50 "Rebalanced index for component: {} (target recall: {:.2})",
51 anomaly.component, self.target_recall
52 ),
53 }
54 }
55}
56
57pub struct PatternResetStrategy {
58 quality_threshold: f64,
59}
60
61impl PatternResetStrategy {
62 pub fn new(quality_threshold: f64) -> Self {
63 Self { quality_threshold }
64 }
65}
66
67impl RepairStrategy for PatternResetStrategy {
68 fn name(&self) -> &str {
69 "pattern_reset"
70 }
71
72 fn can_repair(&self, anomaly: &Anomaly) -> bool {
73 matches!(
74 anomaly.anomaly_type,
75 AnomalyType::PatternDrift | AnomalyType::LearningStall
76 )
77 }
78
79 fn repair(&self, anomaly: &Anomaly) -> RepairResult {
80 let start = std::time::Instant::now();
81
82 std::thread::sleep(std::time::Duration::from_millis(5));
84
85 RepairResult {
86 strategy_name: self.name().to_string(),
87 success: true,
88 duration_ms: start.elapsed().as_secs_f64() * 1000.0,
89 details: format!(
90 "Reset patterns below quality {} for component: {}",
91 self.quality_threshold, anomaly.component
92 ),
93 }
94 }
95}
96
97pub struct CacheFlushStrategy;
98
99impl RepairStrategy for CacheFlushStrategy {
100 fn name(&self) -> &str {
101 "cache_flush"
102 }
103
104 fn can_repair(&self, anomaly: &Anomaly) -> bool {
105 matches!(
106 anomaly.anomaly_type,
107 AnomalyType::CacheEviction | AnomalyType::MemoryPressure
108 )
109 }
110
111 fn repair(&self, anomaly: &Anomaly) -> RepairResult {
112 let start = std::time::Instant::now();
113
114 std::thread::sleep(std::time::Duration::from_millis(2));
116
117 RepairResult {
118 strategy_name: self.name().to_string(),
119 success: true,
120 duration_ms: start.elapsed().as_secs_f64() * 1000.0,
121 details: format!(
122 "Flushed attention and pattern caches for component: {}",
123 anomaly.component
124 ),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_index_rebalance_strategy() {
135 let strategy = IndexRebalanceStrategy::new(0.95);
136 let anomaly = Anomaly {
137 anomaly_type: AnomalyType::LatencySpike,
138 z_score: 4.5,
139 value: 100.0,
140 expected: 10.0,
141 timestamp: std::time::Instant::now(),
142 component: "hnsw_index".to_string(),
143 };
144
145 assert!(strategy.can_repair(&anomaly));
146 let result = strategy.repair(&anomaly);
147 assert!(result.success);
148 assert!(result.duration_ms > 0.0);
149 }
150
151 #[test]
152 fn test_pattern_reset_strategy() {
153 let strategy = PatternResetStrategy::new(0.8);
154 let anomaly = Anomaly {
155 anomaly_type: AnomalyType::PatternDrift,
156 z_score: 3.2,
157 value: 0.5,
158 expected: 0.9,
159 timestamp: std::time::Instant::now(),
160 component: "pattern_cache".to_string(),
161 };
162
163 assert!(strategy.can_repair(&anomaly));
164 let result = strategy.repair(&anomaly);
165 assert!(result.success);
166 }
167
168 #[test]
169 fn test_cache_flush_strategy() {
170 let strategy = CacheFlushStrategy;
171 let anomaly = Anomaly {
172 anomaly_type: AnomalyType::MemoryPressure,
173 z_score: 5.0,
174 value: 95.0,
175 expected: 60.0,
176 timestamp: std::time::Instant::now(),
177 component: "memory".to_string(),
178 };
179
180 assert!(strategy.can_repair(&anomaly));
181 let result = strategy.repair(&anomaly);
182 assert!(result.success);
183 }
184}