1use crate::error_code::ErrorCode;
16use reqwest::StatusCode;
17use std::error::Error as StdError;
18
19#[derive(Debug, Clone)]
20pub enum RequestKind {
21 QueryStart,
22 QueryPage,
23 QueryKill,
24 QueryFinal,
25 UploadToStage,
26 StreamingLoad,
27 Login,
28 Heartbeat,
29 SessionRefresh,
30 Other(String),
31}
32
33impl RequestKind {
34 fn as_str(&self) -> &str {
35 match self {
36 Self::QueryStart => "query/start",
37 Self::QueryPage => "query/page",
38 Self::QueryKill => "query/kill",
39 Self::QueryFinal => "query/final",
40 Self::UploadToStage => "upload_to_stage",
41 Self::StreamingLoad => "streaming_load",
42 Self::Login => "login",
43 Self::Heartbeat => "heartbeat",
44 Self::SessionRefresh => "session/refresh",
45 Self::Other(v) => v.as_str(),
46 }
47 }
48}
49
50impl std::fmt::Display for RequestKind {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 write!(f, "{}", self.as_str())
53 }
54}
55
56impl From<&str> for RequestKind {
57 fn from(value: &str) -> Self {
58 match value {
59 "query/start" => Self::QueryStart,
60 "query/page" => Self::QueryPage,
61 "query/kill" => Self::QueryKill,
62 "query/final" => Self::QueryFinal,
63 "upload_to_stage" => Self::UploadToStage,
64 "streaming_load" => Self::StreamingLoad,
65 "login" => Self::Login,
66 "heartbeat" => Self::Heartbeat,
67 "session/refresh" => Self::SessionRefresh,
68 other => Self::Other(other.to_string()),
69 }
70 }
71}
72
73impl From<String> for RequestKind {
74 fn from(value: String) -> Self {
75 Self::from(value.as_str())
76 }
77}
78
79#[derive(Debug)]
80pub enum Error {
81 WithContext {
82 inner: Box<Error>,
83 request_kind: Option<RequestKind>,
84 query_id: Option<String>,
85 retry_times: Option<u32>,
86 },
87
88 BadArgument(String),
91 IO(String),
95
96 Request(String),
98
99 Decode(String),
103
104 QueryFailed(ErrorCode),
106
107 Logic(StatusCode, ErrorCode),
109
110 Response {
112 status: StatusCode,
113 msg: String,
114 },
115
116 QueryNotFound(String),
126 AuthFailure(ErrorCode),
127}
128
129impl Error {
130 pub fn response_error(status: StatusCode, body: &[u8]) -> Self {
131 Self::Response {
132 status,
133 msg: String::from_utf8_lossy(body).to_string(),
134 }
135 }
136
137 pub fn with_context(self, request_kind: impl Into<RequestKind>) -> Self {
138 Self::WithContext {
139 inner: Box::new(self),
140 request_kind: Some(request_kind.into()),
141 query_id: None,
142 retry_times: None,
143 }
144 }
145
146 pub fn with_query_id(self, query_id: impl Into<String>) -> Self {
147 match self {
148 Self::WithContext {
149 inner,
150 request_kind,
151 retry_times,
152 ..
153 } => Self::WithContext {
154 inner,
155 request_kind,
156 query_id: Some(query_id.into()),
157 retry_times,
158 },
159 other => Self::WithContext {
160 inner: Box::new(other),
161 request_kind: None,
162 query_id: Some(query_id.into()),
163 retry_times: None,
164 },
165 }
166 }
167
168 pub fn with_retry_times(self, retry_times: u32) -> Self {
169 match self {
170 Self::WithContext {
171 inner,
172 request_kind,
173 query_id,
174 ..
175 } => Self::WithContext {
176 inner,
177 request_kind,
178 query_id,
179 retry_times: Some(retry_times),
180 },
181 other => Self::WithContext {
182 inner: Box::new(other),
183 request_kind: None,
184 query_id: None,
185 retry_times: Some(retry_times),
186 },
187 }
188 }
189
190 pub fn status_code(&self) -> Option<StatusCode> {
191 match self {
192 Self::Logic(status, ..) => Some(*status),
193 Self::Response { status, .. } => Some(*status),
194 Self::WithContext { inner, .. } => inner.status_code(),
195 _ => None,
196 }
197 }
198}
199
200impl std::fmt::Display for Error {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 match self {
203 Self::Decode(msg) => write!(f, "DecodeError: {msg}"),
204 Self::BadArgument(msg) => write!(f, "BadArgument: {msg}"),
205 Self::Request(msg) => write!(f, "{msg}"),
206 Self::Response { msg, status } => write!(f, "ResponseError: ({status}){msg}"),
207 Self::IO(msg) => write!(f, "IOError: {msg}"),
208 Self::Logic(status_code, ec) => write!(f, "BadRequest:({status_code}){ec}"),
209 Self::QueryNotFound(msg) => write!(f, "QueryNotFound: {msg}"),
210 Self::QueryFailed(ec) => write!(f, "QueryFailed: {ec}"),
211 Self::AuthFailure(ec) => write!(f, "AuthFailure: {ec}"),
212 Self::WithContext {
213 inner,
214 request_kind,
215 query_id,
216 retry_times,
217 } => {
218 write!(f, "[")?;
219 if let Some(v) = request_kind {
220 write!(f, "request_kind={v}")?;
221 }
222 if let Some(v) = query_id {
223 write!(f, " query_id={v}")?;
224 }
225 if let Some(v) = retry_times {
226 if *v > 1 {
227 write!(f, " retry_times={v}")?;
228 }
229 }
230 write!(f, "]: {inner}")
231 }
232 }
233 }
234}
235
236impl std::error::Error for Error {}
237
238pub type Result<T, E = Error> = core::result::Result<T, E>;
239
240impl From<url::ParseError> for Error {
241 fn from(e: url::ParseError) -> Self {
242 Error::Decode(e.to_string())
243 }
244}
245
246impl From<std::num::ParseIntError> for Error {
247 fn from(e: std::num::ParseIntError) -> Self {
248 Error::Decode(e.to_string())
249 }
250}
251
252impl From<reqwest::header::InvalidHeaderValue> for Error {
254 fn from(e: reqwest::header::InvalidHeaderValue) -> Self {
255 Error::BadArgument(e.to_string())
256 }
257}
258
259impl From<serde_json::Error> for Error {
260 fn from(e: serde_json::Error) -> Self {
261 Error::Decode(e.to_string())
262 }
263}
264
265impl From<reqwest::Error> for Error {
266 fn from(e: reqwest::Error) -> Self {
267 let e = e.without_url();
268 let mut source_chain = String::new();
269 let mut current = e.source();
270 if current.is_some() {
271 source_chain.push_str(", source_chain=");
272 }
273 let mut first = true;
274 while let Some(source) = current {
275 if !first {
276 source_chain.push_str(" -> ");
277 }
278 first = false;
279 source_chain.push_str(&source.to_string());
280 current = source.source();
281 }
282 Error::Request(format!("reqwest::Error: {}{}", e, source_chain))
283 }
284}
285
286impl From<std::io::Error> for Error {
287 fn from(e: std::io::Error) -> Self {
288 Error::IO(e.to_string())
289 }
290}
291
292impl From<std::str::Utf8Error> for Error {
293 fn from(e: std::str::Utf8Error) -> Self {
294 Error::Decode(e.to_string())
295 }
296}