daedalus_runtime/executor/
errors.rs

1/// Structured node error for better diagnostics.
2///
3/// ```
4/// use daedalus_runtime::executor::NodeError;
5/// let err = NodeError::InvalidInput("missing".into());
6/// assert_eq!(err.code(), "invalid_input");
7/// ```
8#[non_exhaustive]
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum NodeError {
11    Handler(String),
12    InvalidInput(String),
13    BackpressureDrop(String),
14}
15
16impl std::fmt::Display for NodeError {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        match self {
19            NodeError::Handler(s) => write!(f, "{s}"),
20            NodeError::InvalidInput(s) => write!(f, "invalid input: {s}"),
21            NodeError::BackpressureDrop(s) => write!(f, "backpressure drop: {s}"),
22        }
23    }
24}
25
26impl std::error::Error for NodeError {}
27
28impl NodeError {
29    /// Return a stable string code for this error.
30    pub fn code(&self) -> &'static str {
31        match self {
32            NodeError::Handler(_) => "handler_error",
33            NodeError::InvalidInput(_) => "invalid_input",
34            NodeError::BackpressureDrop(_) => "backpressure_drop",
35        }
36    }
37
38    /// Whether the error is retryable.
39    pub fn retryable(&self) -> bool {
40        matches!(self, NodeError::BackpressureDrop(_))
41    }
42}
43
44/// Execution errors surfaced by the runtime executor.
45///
46/// ```
47/// use daedalus_runtime::executor::ExecuteError;
48/// let err = ExecuteError::HandlerPanicked { node: "n1".into(), message: "boom".into() };
49/// assert_eq!(err.code(), "handler_panicked");
50/// ```
51#[non_exhaustive]
52#[derive(Debug, PartialEq, Eq)]
53pub enum ExecuteError {
54    /// GPU is required for a segment but no GPU handle is available.
55    GpuUnavailable {
56        segment: Vec<daedalus_planner::NodeRef>,
57    },
58    /// Handler failed with a message.
59    HandlerFailed { node: String, error: NodeError },
60    /// Handler panicked (caught and converted into an error).
61    HandlerPanicked { node: String, message: String },
62}
63
64impl std::fmt::Display for ExecuteError {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        match self {
67            ExecuteError::GpuUnavailable { .. } => write!(f, "gpu unavailable for segment"),
68            ExecuteError::HandlerFailed { node, error } => {
69                write!(f, "handler failed on node {node}: {error}")
70            }
71            ExecuteError::HandlerPanicked { node, message } => {
72                write!(f, "handler panicked on node {node}: {message}")
73            }
74        }
75    }
76}
77
78impl std::error::Error for ExecuteError {}
79
80impl ExecuteError {
81    /// Return a stable string code for this error.
82    pub fn code(&self) -> &'static str {
83        match self {
84            ExecuteError::GpuUnavailable { .. } => "gpu_unavailable",
85            ExecuteError::HandlerFailed { .. } => "handler_failed",
86            ExecuteError::HandlerPanicked { .. } => "handler_panicked",
87        }
88    }
89
90    /// Whether the error is retryable.
91    pub fn retryable(&self) -> bool {
92        matches!(self, ExecuteError::GpuUnavailable { .. })
93    }
94}