ralph_workflow/reducer/state/continuation/loop_detection.rs
1//! Loop detection and effect fingerprinting.
2//!
3//! Provides methods for detecting infinite tight loops by tracking consecutive
4//! identical effects. When the same effect is executed too many times in a row,
5//! the system triggers loop recovery to break the cycle.
6
7use super::state::ContinuationState;
8
9impl ContinuationState {
10 /// Update loop detection counters based on the current effect fingerprint.
11 ///
12 /// This method updates `last_effect_kind` and `consecutive_same_effect_count`
13 /// based on whether the current effect fingerprint matches the previous one.
14 ///
15 /// # Returns
16 ///
17 /// A new `ContinuationState` with updated loop detection counters.
18 ///
19 /// # Behavior
20 ///
21 /// - If `current_fingerprint` equals `last_effect_kind`: increment `consecutive_same_effect_count`
22 /// - Otherwise: reset `consecutive_same_effect_count` to 1 and update `last_effect_kind`
23 #[must_use]
24 pub fn update_loop_detection_counters(self, current_fingerprint: String) -> Self {
25 if self.last_effect_kind.as_deref() == Some(¤t_fingerprint) {
26 Self {
27 consecutive_same_effect_count: self.consecutive_same_effect_count.saturating_add(1),
28 ..self
29 }
30 } else {
31 Self {
32 last_effect_kind: Some(current_fingerprint),
33 consecutive_same_effect_count: 1,
34 ..self
35 }
36 }
37 }
38
39 /// Check if loop detection threshold has been exceeded.
40 ///
41 /// Returns `true` if `consecutive_same_effect_count` >= `max_consecutive_same_effect`.
42 #[must_use]
43 pub const fn is_loop_detected(&self) -> bool {
44 self.consecutive_same_effect_count >= self.max_consecutive_same_effect
45 }
46}