Skip to main content

rust_supervisor/dashboard/
error.rs

1//! Structured dashboard IPC errors.
2//!
3//! The dashboard feature exchanges errors with relay code over JSON. This
4//! module keeps those errors typed so tests can assert code, stage, target, and
5//! retry behavior without parsing strings.
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use thiserror::Error;
10
11/// Error returned by target-side dashboard IPC handlers.
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Error)]
13#[error("{code} at {stage}: {message}")]
14pub struct DashboardError {
15    /// Stable machine-readable error code.
16    pub code: String,
17    /// Processing stage that produced the error.
18    pub stage: String,
19    /// Optional target process identifier related to the error.
20    pub target_id: Option<String>,
21    /// Human-readable diagnostic message.
22    pub message: String,
23    /// Whether a caller can retry after the reported condition changes.
24    pub retryable: bool,
25}
26
27impl DashboardError {
28    /// Creates a structured dashboard error.
29    ///
30    /// # Arguments
31    ///
32    /// - `code`: Stable machine-readable error code.
33    /// - `stage`: Processing stage that produced the error.
34    /// - `target_id`: Optional target process identifier.
35    /// - `message`: Human-readable diagnostic message.
36    /// - `retryable`: Whether a retry can later succeed.
37    ///
38    /// # Returns
39    ///
40    /// Returns a [`DashboardError`] value ready for JSON serialization.
41    pub fn new(
42        code: impl Into<String>,
43        stage: impl Into<String>,
44        target_id: Option<String>,
45        message: impl Into<String>,
46        retryable: bool,
47    ) -> Self {
48        Self {
49            code: code.into(),
50            stage: stage.into(),
51            target_id,
52            message: message.into(),
53            retryable,
54        }
55    }
56
57    /// Creates an unsupported method error.
58    ///
59    /// # Arguments
60    ///
61    /// - `method`: Method name rejected by the parser.
62    ///
63    /// # Returns
64    ///
65    /// Returns a non-retryable [`DashboardError`].
66    pub fn unsupported_method(method: impl AsRef<str>) -> Self {
67        Self::new(
68            "unsupported_method",
69            "protocol_parse",
70            None,
71            format!("unsupported dashboard IPC method {}", method.as_ref()),
72            false,
73        )
74    }
75
76    /// Creates a validation error.
77    ///
78    /// # Arguments
79    ///
80    /// - `stage`: Validation stage.
81    /// - `target_id`: Optional target process identifier.
82    /// - `message`: Human-readable validation message.
83    ///
84    /// # Returns
85    ///
86    /// Returns a non-retryable [`DashboardError`].
87    pub fn validation(
88        stage: impl Into<String>,
89        target_id: Option<String>,
90        message: impl Into<String>,
91    ) -> Self {
92        Self::new("validation_failed", stage, target_id, message, false)
93    }
94
95    /// Creates a target unavailable error.
96    ///
97    /// # Arguments
98    ///
99    /// - `stage`: Processing stage that tried to use the target.
100    /// - `target_id`: Target process identifier.
101    /// - `message`: Human-readable diagnostic message.
102    ///
103    /// # Returns
104    ///
105    /// Returns a retryable [`DashboardError`].
106    pub fn target_unavailable(
107        stage: impl Into<String>,
108        target_id: impl Into<String>,
109        message: impl Into<String>,
110    ) -> Self {
111        Self::new(
112            "target_unavailable",
113            stage,
114            Some(target_id.into()),
115            message,
116            true,
117        )
118    }
119}