byteor_actions/
error.rs

1use core::fmt;
2
3/// Whether an action failure is retryable.
4#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5pub enum FailureClass {
6    /// A transient/contended failure where retrying may succeed.
7    Retryable,
8    /// A permanent/config/contract failure where retrying is unlikely to help.
9    NonRetryable,
10}
11
12impl FailureClass {
13    /// Stable string representation.
14    pub fn as_str(&self) -> &'static str {
15        match self {
16            FailureClass::Retryable => "retryable",
17            FailureClass::NonRetryable => "non_retryable",
18        }
19    }
20}
21
22/// A typed error returned by action stages.
23#[derive(Debug)]
24pub struct ActionError {
25    /// Retry classification.
26    pub class: FailureClass,
27    /// Human-readable details.
28    pub message: String,
29}
30
31impl ActionError {
32    /// Create a retryable action error.
33    pub fn retryable(message: impl Into<String>) -> Self {
34        Self {
35            class: FailureClass::Retryable,
36            message: message.into(),
37        }
38    }
39
40    /// Create a non-retryable action error.
41    pub fn non_retryable(message: impl Into<String>) -> Self {
42        Self {
43            class: FailureClass::NonRetryable,
44            message: message.into(),
45        }
46    }
47}
48
49impl fmt::Display for ActionError {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        write!(
52            f,
53            "byteor_action_error class={} message={}",
54            self.class.as_str(),
55            self.message
56        )
57    }
58}
59
60impl std::error::Error for ActionError {}