wp_error/error_handling/
strategy.rs

1use orion_error::ErrStrategy;
2use serde::{Deserialize, Serialize};
3use std::{
4    fmt::Formatter,
5    sync::atomic::{AtomicU8, Ordering},
6};
7use wp_log::{error_ctrl, warn_ctrl};
8
9pub enum ErrorHandlingStrategy {
10    FixRetry,
11    Tolerant,
12    Throw,
13    Ignore,
14    Terminate,
15}
16
17impl From<ErrStrategy> for ErrorHandlingStrategy {
18    fn from(value: ErrStrategy) -> Self {
19        match value {
20            ErrStrategy::Retry => ErrorHandlingStrategy::FixRetry,
21            ErrStrategy::Ignore => ErrorHandlingStrategy::Ignore,
22            ErrStrategy::Throw => ErrorHandlingStrategy::Throw,
23        }
24    }
25}
26
27static ROBUST_MODE: AtomicU8 = AtomicU8::new(0);
28//static mut ROBUST_MODE: RobustnessMode = RobustnessMode::Debug;
29
30pub fn sys_robust_mode() -> RobustnessMode {
31    match ROBUST_MODE.load(Ordering::SeqCst) {
32        0 => RobustnessMode::Debug,
33        1 => RobustnessMode::Normal,
34        2 => RobustnessMode::Strict,
35        _ => unreachable!("Invalid robustness mode"),
36    }
37}
38
39pub fn switch_sys_robust_mode(mode: RobustnessMode) -> RobustnessMode {
40    let old = sys_robust_mode();
41    let new_mode = match mode {
42        RobustnessMode::Debug => 0,
43        RobustnessMode::Normal => 1,
44        RobustnessMode::Strict => 2,
45    };
46    // runtime-level change is part of engine control plane
47    warn_ctrl!("switch robust mode from {} to {}", old, mode);
48    ROBUST_MODE.store(new_mode, Ordering::SeqCst);
49    old
50}
51
52#[derive(Debug, Default, PartialEq, Deserialize, Serialize, Clone)]
53pub enum RobustnessMode {
54    #[default]
55    #[serde(rename = "debug")]
56    Debug,
57    #[serde(rename = "normal")]
58    Normal,
59    #[serde(rename = "strict")]
60    Strict,
61}
62
63impl From<&str> for RobustnessMode {
64    fn from(s: &str) -> Self {
65        match s {
66            "debug" => RobustnessMode::Debug,
67            "normal" => RobustnessMode::Normal,
68            "strict" => RobustnessMode::Strict,
69            other => {
70                // Fallback to debug to avoid panic in production; log a warning.
71                error_ctrl!("unknown robust mode '{}', fallback to 'debug'", other);
72                RobustnessMode::Debug
73            }
74        }
75    }
76}
77
78impl std::fmt::Display for RobustnessMode {
79    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
80        match self {
81            RobustnessMode::Debug => write!(f, "debug"),
82            RobustnessMode::Normal => write!(f, "normal"),
83            RobustnessMode::Strict => write!(f, "strict"),
84        }
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_robustness_mode_default() {
94        let mode = RobustnessMode::default();
95        assert_eq!(mode, RobustnessMode::Debug);
96    }
97
98    #[test]
99    fn test_robustness_mode_from_str_debug() {
100        let mode = RobustnessMode::from("debug");
101        assert_eq!(mode, RobustnessMode::Debug);
102    }
103
104    #[test]
105    fn test_robustness_mode_from_str_normal() {
106        let mode = RobustnessMode::from("normal");
107        assert_eq!(mode, RobustnessMode::Normal);
108    }
109
110    #[test]
111    fn test_robustness_mode_from_str_strict() {
112        let mode = RobustnessMode::from("strict");
113        assert_eq!(mode, RobustnessMode::Strict);
114    }
115
116    #[test]
117    fn test_robustness_mode_from_str_unknown() {
118        let mode = RobustnessMode::from("unknown");
119        assert_eq!(mode, RobustnessMode::Debug); // fallback
120    }
121
122    #[test]
123    fn test_robustness_mode_display() {
124        assert_eq!(RobustnessMode::Debug.to_string(), "debug");
125        assert_eq!(RobustnessMode::Normal.to_string(), "normal");
126        assert_eq!(RobustnessMode::Strict.to_string(), "strict");
127    }
128
129    #[test]
130    fn test_robustness_mode_serde() {
131        let json = "\"debug\"";
132        let mode: RobustnessMode = serde_json::from_str(json).unwrap();
133        assert_eq!(mode, RobustnessMode::Debug);
134
135        let json = "\"normal\"";
136        let mode: RobustnessMode = serde_json::from_str(json).unwrap();
137        assert_eq!(mode, RobustnessMode::Normal);
138
139        let json = "\"strict\"";
140        let mode: RobustnessMode = serde_json::from_str(json).unwrap();
141        assert_eq!(mode, RobustnessMode::Strict);
142    }
143
144    #[test]
145    fn test_robustness_mode_serialize() {
146        assert_eq!(
147            serde_json::to_string(&RobustnessMode::Debug).unwrap(),
148            "\"debug\""
149        );
150        assert_eq!(
151            serde_json::to_string(&RobustnessMode::Normal).unwrap(),
152            "\"normal\""
153        );
154        assert_eq!(
155            serde_json::to_string(&RobustnessMode::Strict).unwrap(),
156            "\"strict\""
157        );
158    }
159
160    #[test]
161    fn test_robustness_mode_clone() {
162        let mode = RobustnessMode::Normal;
163        let cloned = mode.clone();
164        assert_eq!(mode, cloned);
165    }
166
167    #[test]
168    fn test_error_handling_strategy_from_err_strategy() {
169        let retry: ErrorHandlingStrategy = ErrStrategy::Retry.into();
170        matches!(retry, ErrorHandlingStrategy::FixRetry);
171
172        let ignore: ErrorHandlingStrategy = ErrStrategy::Ignore.into();
173        matches!(ignore, ErrorHandlingStrategy::Ignore);
174
175        let throw: ErrorHandlingStrategy = ErrStrategy::Throw.into();
176        matches!(throw, ErrorHandlingStrategy::Throw);
177    }
178}