Skip to main content

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    pub fn update_loop_detection_counters(&self, current_fingerprint: String) -> Self {
24        if self.last_effect_kind.as_deref() == Some(&current_fingerprint) {
25            // Same effect as last time - increment counter
26            Self {
27                consecutive_same_effect_count: self.consecutive_same_effect_count + 1,
28                ..self.clone()
29            }
30        } else {
31            // Different effect - reset counter and update fingerprint
32            Self {
33                last_effect_kind: Some(current_fingerprint),
34                consecutive_same_effect_count: 1,
35                ..self.clone()
36            }
37        }
38    }
39
40    /// Check if loop detection threshold has been exceeded.
41    ///
42    /// Returns `true` if `consecutive_same_effect_count` >= `max_consecutive_same_effect`.
43    pub fn is_loop_detected(&self) -> bool {
44        self.consecutive_same_effect_count >= self.max_consecutive_same_effect
45    }
46}