zerokms_protocol/
error.rs1use static_assertions::assert_impl_all;
2use std::error::Error as StdError;
3use thiserror::Error;
4
5pub trait RetryableError {
6 fn can_retry(&self) -> bool;
7}
8
9type ShareableError = Box<dyn StdError + Send + Sync>;
10
11#[derive(Debug)]
12pub enum ViturRequestErrorKind {
13 PrepareRequest,
14 SendRequest,
15 NotFound,
16 Conflict,
17 FailureResponse,
18 ParseResponse,
19 Unauthorized,
20 Forbidden,
21 Other,
22}
23
24impl std::fmt::Display for ViturRequestErrorKind {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 write!(
27 f,
28 "{}",
29 match self {
30 Self::PrepareRequest => "PrepareRequest",
31 Self::SendRequest => "SendRequest",
32 Self::NotFound => "NotFound",
33 Self::Conflict => "Conflict",
34 Self::FailureResponse => "FailureResponse",
35 Self::ParseResponse => "ParseResponse",
36 Self::Unauthorized => "Unauthorized",
37 Self::Forbidden => "Forbidden",
38 Self::Other => "Other",
39 }
40 )
41 }
42}
43
44#[derive(Debug, Error)]
45#[error("{kind}: {message}")]
46pub struct ViturRequestError {
47 pub kind: ViturRequestErrorKind,
48 pub message: &'static str,
49 #[source]
56 pub error: ShareableError,
57 can_retry: bool,
58}
59
60assert_impl_all!(ViturRequestError: Send, Sync);
63
64impl ViturRequestError {
65 #[inline]
66 pub fn new(
67 kind: ViturRequestErrorKind,
68 message: &'static str,
69 error: impl StdError + 'static + Send + Sync,
70 ) -> Self {
71 Self {
72 kind,
73 message,
74 error: Box::new(error),
75 can_retry: false,
76 }
77 }
78
79 #[inline]
80 pub fn prepare(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
81 Self {
82 kind: ViturRequestErrorKind::PrepareRequest,
83 message,
84 error: Box::new(error),
85 can_retry: false,
86 }
87 }
88
89 #[inline]
90 pub fn parse(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
91 Self {
92 kind: ViturRequestErrorKind::ParseResponse,
93 message,
94 error: Box::new(error),
95 can_retry: false,
96 }
97 }
98
99 #[inline]
100 pub fn send(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
101 Self {
102 kind: ViturRequestErrorKind::SendRequest,
103 message,
104 error: Box::new(error),
105 can_retry: false,
106 }
107 }
108
109 #[inline]
110 pub fn not_found(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
111 Self {
112 kind: ViturRequestErrorKind::NotFound,
113 message,
114 error: Box::new(error),
115 can_retry: false,
116 }
117 }
118
119 #[inline]
120 pub fn conflict(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
121 Self {
122 kind: ViturRequestErrorKind::Conflict,
123 message,
124 error: Box::new(error),
125 can_retry: false,
126 }
127 }
128
129 #[inline]
130 pub fn response(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
131 Self {
132 kind: ViturRequestErrorKind::FailureResponse,
133 message,
134 error: Box::new(error),
135 can_retry: false,
136 }
137 }
138
139 #[inline]
140 pub fn forbidden(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
141 Self {
142 kind: ViturRequestErrorKind::Forbidden,
143 message,
144 error: Box::new(error),
145 can_retry: false,
146 }
147 }
148
149 #[inline]
150 pub fn other(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
151 Self {
152 kind: ViturRequestErrorKind::Other,
153 message,
154 error: Box::new(error),
155 can_retry: false,
156 }
157 }
158
159 pub fn is_conflict(&self) -> bool {
160 matches!(self.kind, ViturRequestErrorKind::Conflict)
161 }
162
163 pub fn with_retryable(mut self, can_retry: bool) -> Self {
164 self.can_retry = can_retry;
165 self
166 }
167
168 pub fn retryable(self) -> Self {
169 self.with_retryable(true)
170 }
171}
172
173impl RetryableError for ViturRequestError {
174 fn can_retry(&self) -> bool {
175 self.can_retry
176 }
177}