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}: {error}")]
46pub struct ViturRequestError {
47 pub kind: ViturRequestErrorKind,
48 pub message: &'static str,
49 pub error: ShareableError,
50 can_retry: bool,
51}
52
53assert_impl_all!(ViturRequestError: Send, Sync);
56
57impl ViturRequestError {
58 #[inline]
59 pub fn new(
60 kind: ViturRequestErrorKind,
61 message: &'static str,
62 error: impl StdError + 'static + Send + Sync,
63 ) -> Self {
64 Self {
65 kind,
66 message,
67 error: Box::new(error),
68 can_retry: false,
69 }
70 }
71
72 #[inline]
73 pub fn prepare(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
74 Self {
75 kind: ViturRequestErrorKind::PrepareRequest,
76 message,
77 error: Box::new(error),
78 can_retry: false,
79 }
80 }
81
82 #[inline]
83 pub fn parse(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
84 Self {
85 kind: ViturRequestErrorKind::ParseResponse,
86 message,
87 error: Box::new(error),
88 can_retry: false,
89 }
90 }
91
92 #[inline]
93 pub fn send(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
94 Self {
95 kind: ViturRequestErrorKind::SendRequest,
96 message,
97 error: Box::new(error),
98 can_retry: false,
99 }
100 }
101
102 #[inline]
103 pub fn not_found(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
104 Self {
105 kind: ViturRequestErrorKind::NotFound,
106 message,
107 error: Box::new(error),
108 can_retry: false,
109 }
110 }
111
112 #[inline]
113 pub fn conflict(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
114 Self {
115 kind: ViturRequestErrorKind::Conflict,
116 message,
117 error: Box::new(error),
118 can_retry: false,
119 }
120 }
121
122 #[inline]
123 pub fn response(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
124 Self {
125 kind: ViturRequestErrorKind::FailureResponse,
126 message,
127 error: Box::new(error),
128 can_retry: false,
129 }
130 }
131
132 #[inline]
133 pub fn forbidden(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
134 Self {
135 kind: ViturRequestErrorKind::Forbidden,
136 message,
137 error: Box::new(error),
138 can_retry: false,
139 }
140 }
141
142 #[inline]
143 pub fn other(message: &'static str, error: impl StdError + 'static + Send + Sync) -> Self {
144 Self {
145 kind: ViturRequestErrorKind::Other,
146 message,
147 error: Box::new(error),
148 can_retry: false,
149 }
150 }
151
152 pub fn is_conflict(&self) -> bool {
153 matches!(self.kind, ViturRequestErrorKind::Conflict)
154 }
155
156 pub fn with_retryable(mut self, can_retry: bool) -> Self {
157 self.can_retry = can_retry;
158 self
159 }
160
161 pub fn retryable(self) -> Self {
162 self.with_retryable(true)
163 }
164}
165
166impl RetryableError for ViturRequestError {
167 fn can_retry(&self) -> bool {
168 self.can_retry
169 }
170}