dragonfly_client_core/error/
mod.rs1pub mod errors;
18pub mod message;
19
20pub use errors::ErrorType;
21pub use errors::ExternalError;
22
23pub use errors::OrErr;
24pub use errors::{BackendError, DownloadFromParentFailed};
25
26#[derive(thiserror::Error, Debug)]
28pub enum DFError {
29 #[error(transparent)]
31 IO(#[from] std::io::Error),
32
33 #[error(transparent)]
35 VarError(#[from] std::env::VarError),
36
37 #[error("mpsc send: {0}")]
39 MpscSend(String),
40
41 #[error("send timeout")]
43 SendTimeout,
44
45 #[error{"hashring {0} is failed"}]
47 HashRing(String),
48
49 #[error("no space left on device: {0}")]
51 NoSpace(String),
52
53 #[error{"host {0} not found"}]
55 HostNotFound(String),
56
57 #[error{"task {0} not found"}]
59 TaskNotFound(String),
60
61 #[error{"piece {0} not found"}]
63 PieceNotFound(String),
64
65 #[error{"piece {0} state is failed"}]
67 PieceStateIsFailed(String),
68
69 #[error{"download piece {0} finished timeout"}]
71 DownloadPieceFinishedTimeout(String),
72
73 #[error{"wait for piece {0} finished timeout"}]
75 WaitForPieceFinishedTimeout(String),
76
77 #[error{"available manager not found"}]
79 AvailableManagerNotFound,
80
81 #[error{"available schedulers not found"}]
83 AvailableSchedulersNotFound,
84
85 #[error(transparent)]
87 DownloadFromParentFailed(DownloadFromParentFailed),
88
89 #[error{"column family {0} not found"}]
91 ColumnFamilyNotFound(String),
92
93 #[error{"can not transit from {0} to {1}"}]
95 InvalidStateTransition(String, String),
96
97 #[error{"invalid state {0}"}]
99 InvalidState(String),
100
101 #[error("invalid uri {0}")]
103 InvalidURI(String),
104
105 #[error("invalid peer {0}")]
107 InvalidPeer(String),
108
109 #[error{"scheduler client not found"}]
111 SchedulerClientNotFound,
112
113 #[error{"unexpected response"}]
115 UnexpectedResponse,
116
117 #[error{"digest mismatch expected: {0}, actual: {1}"}]
119 DigestMismatch(String, String),
120
121 #[error("content length mismatch expected: {0}, actual: {1}")]
123 ContentLengthMismatch(u64, u64),
124
125 #[error("max schedule count {0} exceeded")]
127 MaxScheduleCountExceeded(u32),
128
129 #[error("invalid content length")]
131 InvalidContentLength,
132
133 #[error("invalid piece length")]
135 InvalidPieceLength,
136
137 #[error("invalid parameter")]
139 InvalidParameter,
140
141 #[error(transparent)]
143 NetAddrParseError(#[from] std::net::AddrParseError),
144
145 #[error(transparent)]
147 ConvertInfallible(#[from] std::convert::Infallible),
148
149 #[error(transparent)]
151 Utf8(#[from] std::str::Utf8Error),
152
153 #[error("mutex poisoned: {0}")]
155 MutexPoisoned(String),
156
157 #[error("unknown {0}")]
159 Unknown(String),
160
161 #[error{"unimplemented"}]
163 Unimplemented,
164
165 #[error{"permission denied"}]
167 PermissionDenied,
168
169 #[error{"RangeUnsatisfiable: Failed to parse range fallback error, please file an issue"}]
171 EmptyHTTPRangeError,
172
173 #[error{"unauthorized"}]
175 Unauthorized,
176
177 #[error(transparent)]
179 ArrayTryFromSliceError(#[from] std::array::TryFromSliceError),
180
181 #[error("vortex protocol status: code={0:?}, message={1}")]
183 VortexProtocolStatus(vortex_protocol::tlv::error::Code, String),
184
185 #[error(transparent)]
187 VortexProtocolError(#[from] vortex_protocol::error::Error),
188
189 #[error(transparent)]
191 TonicStatus(#[from] tonic::Status),
192
193 #[error(transparent)]
195 TonicTransportError(#[from] tonic::transport::Error),
196
197 #[error(transparent)]
199 TonicReflectionServerError(#[from] tonic_reflection::server::Error),
200
201 #[error(transparent)]
203 TokioStreamElapsed(#[from] tokio_stream::Elapsed),
204
205 #[error(transparent)]
207 TokioTimeErrorElapsed(#[from] tokio::time::error::Elapsed),
208
209 #[error(transparent)]
211 HTTTHeaderInvalidHeaderName(#[from] http::header::InvalidHeaderName),
212
213 #[error(transparent)]
215 HTTTHeaderInvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
216
217 #[error(transparent)]
219 HTTTHeaderToStrError(#[from] http::header::ToStrError),
220
221 #[error(transparent)]
223 URLParseError(#[from] url::ParseError),
224
225 #[error(transparent)]
227 ReqwestError(#[from] reqwest::Error),
228
229 #[error(transparent)]
231 ReqwestMiddlewareError(#[from] reqwest_middleware::Error),
232
233 #[error(transparent)]
235 OpenDALError(#[from] opendal::Error),
236
237 #[error(transparent)]
239 HyperError(#[from] hyper::Error),
240
241 #[error(transparent)]
243 BackendError(Box<BackendError>),
244
245 #[error(transparent)]
247 HyperUtilClientLegacyError(#[from] hyper_util::client::legacy::Error),
248
249 #[error(transparent)]
251 ExternalError(#[from] ExternalError),
252
253 #[error(
255 "exceeded the maximum download limit of {0} files. Use --max-files to increase this limit"
256 )]
257 MaxDownloadFilesExceeded(usize),
258
259 #[error("unsupported {0}")]
261 Unsupported(String),
262
263 #[error(transparent)]
265 TokioJoinError(tokio::task::JoinError),
266
267 #[error("validate failed: {0}")]
269 ValidationError(String),
270
271 #[cfg(target_os = "linux")]
273 #[error(transparent)]
274 CgroupsFSError(#[from] cgroups_rs::fs::error::Error),
275}
276
277impl<T> From<tokio::sync::mpsc::error::SendError<T>> for DFError {
279 fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
280 Self::MpscSend(e.to_string())
281 }
282}
283
284impl<T> From<std::sync::PoisonError<T>> for DFError {
286 fn from(e: std::sync::PoisonError<T>) -> Self {
287 Self::MutexPoisoned(e.to_string())
288 }
289}
290
291impl<T> From<tokio::sync::mpsc::error::SendTimeoutError<T>> for DFError {
293 fn from(err: tokio::sync::mpsc::error::SendTimeoutError<T>) -> Self {
294 match err {
295 tokio::sync::mpsc::error::SendTimeoutError::Timeout(_) => Self::SendTimeout,
296 tokio::sync::mpsc::error::SendTimeoutError::Closed(_) => Self::SendTimeout,
297 }
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304 use std::sync::PoisonError;
305 use tokio::sync::mpsc::error::{SendError, SendTimeoutError};
306
307 #[test]
308 fn from_conversions_map_source_errors_to_variants() {
309 let test_cases: Vec<(DFError, fn(DFError))> = vec![
310 (
311 ExternalError::new(ErrorType::StorageError)
312 .with_cause(Box::new(std::io::Error::other("inner error")))
313 .into(),
314 |err| {
315 assert!(matches!(err, DFError::ExternalError(_)));
316 assert_eq!(err.to_string(), "StorageError cause: inner error");
317 },
318 ),
319 (SendError(()).into(), |err| {
320 assert!(matches!(err, DFError::MpscSend(_)));
321 assert_eq!(err.to_string(), "mpsc send: channel closed");
322 }),
323 (PoisonError::new(()).into(), |err| {
324 assert!(matches!(err, DFError::MutexPoisoned(_)));
325 assert_eq!(
326 err.to_string(),
327 "mutex poisoned: poisoned lock: another task failed inside"
328 );
329 }),
330 (SendTimeoutError::Timeout(()).into(), |err| {
331 assert!(matches!(err, DFError::SendTimeout));
332 assert_eq!(err.to_string(), "send timeout");
333 }),
334 (SendTimeoutError::Closed(()).into(), |err| {
335 assert!(matches!(err, DFError::SendTimeout));
336 assert_eq!(err.to_string(), "send timeout");
337 }),
338 ];
339
340 for (err, expect) in test_cases {
341 expect(err);
342 }
343 }
344}