1use crate::types::GatewayErrorBody;
8
9#[derive(Debug, thiserror::Error)]
13pub enum SolariError {
14 #[error("{message}")]
16 Auth { status: u16, message: String, code: Option<String> },
17
18 #[error("{message}")]
20 Plan { status: u16, message: String, code: Option<String> },
21
22 #[error("{message}")]
24 ConcurrencyLimit { status: u16, message: String, code: Option<String> },
25
26 #[error("{message}")]
28 NoCapacity { status: u16, message: String, code: Option<String> },
29
30 #[error("{message}")]
32 Gateway { status: u16, message: String, code: Option<String> },
33
34 #[error("{message}")]
36 Action { method: String, message: String, code: Option<String> },
37
38 #[error("Action \"{method}\" timed out after {timeout_ms}ms")]
40 Timeout { method: String, timeout_ms: u64 },
41
42 #[error("{message}")]
44 Connection { message: String },
45
46 #[error("{message}")]
48 Git { message: String },
49
50 #[error("{0}")]
52 Other(String),
53}
54
55impl SolariError {
56 pub(crate) fn connection(msg: impl Into<String>) -> Self {
57 SolariError::Connection { message: msg.into() }
58 }
59
60 pub fn status(&self) -> Option<u16> {
62 match self {
63 SolariError::Auth { status, .. }
64 | SolariError::Plan { status, .. }
65 | SolariError::ConcurrencyLimit { status, .. }
66 | SolariError::NoCapacity { status, .. }
67 | SolariError::Gateway { status, .. } => Some(*status),
68 _ => None,
69 }
70 }
71}
72
73pub(crate) fn map_gateway_error(status: u16, body: Option<GatewayErrorBody>) -> SolariError {
76 let code = body.as_ref().and_then(|b| b.code.clone());
77 let message = body
78 .as_ref()
79 .and_then(|b| b.message.clone().or_else(|| b.error.clone()).or_else(|| b.code.clone()))
80 .unwrap_or_else(|| format!("Gateway request failed with status {status}"));
81 match status {
82 401 | 403 => SolariError::Auth { status, message, code },
83 402 => SolariError::Plan { status, message, code },
84 429 => SolariError::ConcurrencyLimit { status, message, code },
85 503 => SolariError::NoCapacity { status, message, code },
86 _ => SolariError::Gateway { status, message, code },
87 }
88}
89
90pub(crate) fn is_route_unavailable(err: &SolariError) -> bool {
95 matches!(err.status(), Some(404) | Some(405) | Some(501))
96}