pub mod errors;
pub mod message;
pub use errors::ErrorType;
pub use errors::ExternalError;
pub use errors::OrErr;
pub use errors::{BackendError, DownloadFromParentFailed};
#[derive(thiserror::Error, Debug)]
pub enum DFError {
#[error(transparent)]
IO(#[from] std::io::Error),
#[error(transparent)]
VarError(#[from] std::env::VarError),
#[error("mpsc send: {0}")]
MpscSend(String),
#[error("send timeout")]
SendTimeout,
#[error{"hashring {0} is failed"}]
HashRing(String),
#[error("no space left on device: {0}")]
NoSpace(String),
#[error{"host {0} not found"}]
HostNotFound(String),
#[error{"task {0} not found"}]
TaskNotFound(String),
#[error{"piece {0} not found"}]
PieceNotFound(String),
#[error{"piece {0} state is failed"}]
PieceStateIsFailed(String),
#[error{"download piece {0} finished timeout"}]
DownloadPieceFinishedTimeout(String),
#[error{"wait for piece {0} finished timeout"}]
WaitForPieceFinishedTimeout(String),
#[error{"available manager not found"}]
AvailableManagerNotFound,
#[error{"available schedulers not found"}]
AvailableSchedulersNotFound,
#[error(transparent)]
DownloadFromParentFailed(DownloadFromParentFailed),
#[error{"column family {0} not found"}]
ColumnFamilyNotFound(String),
#[error{"can not transit from {0} to {1}"}]
InvalidStateTransition(String, String),
#[error{"invalid state {0}"}]
InvalidState(String),
#[error("invalid uri {0}")]
InvalidURI(String),
#[error("invalid peer {0}")]
InvalidPeer(String),
#[error{"scheduler client not found"}]
SchedulerClientNotFound,
#[error{"unexpected response"}]
UnexpectedResponse,
#[error{"digest mismatch expected: {0}, actual: {1}"}]
DigestMismatch(String, String),
#[error("content length mismatch expected: {0}, actual: {1}")]
ContentLengthMismatch(u64, u64),
#[error("max schedule count {0} exceeded")]
MaxScheduleCountExceeded(u32),
#[error("invalid content length")]
InvalidContentLength,
#[error("invalid piece length")]
InvalidPieceLength,
#[error("invalid parameter")]
InvalidParameter,
#[error(transparent)]
NetAddrParseError(#[from] std::net::AddrParseError),
#[error(transparent)]
ConvertInfallible(#[from] std::convert::Infallible),
#[error(transparent)]
Utf8(#[from] std::str::Utf8Error),
#[error("unknown {0}")]
Unknown(String),
#[error{"unimplemented"}]
Unimplemented,
#[error{"RangeUnsatisfiable: Failed to parse range fallback error, please file an issue"}]
EmptyHTTPRangeError,
#[error{"unauthorized"}]
Unauthorized,
#[error(transparent)]
ArrayTryFromSliceError(#[from] std::array::TryFromSliceError),
#[error("vortex protocol status: code={0:?}, message={1}")]
VortexProtocolStatus(vortex_protocol::tlv::error::Code, String),
#[error(transparent)]
VortexProtocolError(#[from] vortex_protocol::error::Error),
#[error(transparent)]
TonicStatus(#[from] tonic::Status),
#[error(transparent)]
TonicTransportError(#[from] tonic::transport::Error),
#[error(transparent)]
TonicReflectionServerError(#[from] tonic_reflection::server::Error),
#[error(transparent)]
TokioStreamElapsed(#[from] tokio_stream::Elapsed),
#[error(transparent)]
TokioTimeErrorElapsed(#[from] tokio::time::error::Elapsed),
#[error(transparent)]
HeadersError(#[from] headers::Error),
#[error(transparent)]
HTTTHeaderInvalidHeaderName(#[from] http::header::InvalidHeaderName),
#[error(transparent)]
HTTTHeaderInvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
#[error(transparent)]
HTTTHeaderToStrError(#[from] http::header::ToStrError),
#[error(transparent)]
URLParseError(#[from] url::ParseError),
#[error(transparent)]
ReqwestError(#[from] reqwest::Error),
#[error(transparent)]
ReqwestMiddlewareError(#[from] reqwest_middleware::Error),
#[error(transparent)]
OpenDALError(#[from] opendal::Error),
#[error(transparent)]
HyperError(#[from] hyper::Error),
#[error(transparent)]
BackendError(Box<BackendError>),
#[error(transparent)]
HyperUtilClientLegacyError(#[from] hyper_util::client::legacy::Error),
#[error(transparent)]
ExternalError(#[from] ExternalError),
#[error(
"exceeded the maximum download limit of {0} files. Use --max-files to increase this limit"
)]
MaxDownloadFilesExceeded(usize),
#[error("unsupported {0}")]
Unsupported(String),
#[error(transparent)]
TokioJoinError(tokio::task::JoinError),
#[error("validate failed: {0}")]
ValidationError(String),
#[cfg(target_os = "linux")]
#[error(transparent)]
CgroupsFSError(#[from] cgroups_rs::fs::error::Error),
}
impl<T> From<tokio::sync::mpsc::error::SendError<T>> for DFError {
fn from(e: tokio::sync::mpsc::error::SendError<T>) -> Self {
Self::MpscSend(e.to_string())
}
}
impl<T> From<tokio::sync::mpsc::error::SendTimeoutError<T>> for DFError {
fn from(err: tokio::sync::mpsc::error::SendTimeoutError<T>) -> Self {
match err {
tokio::sync::mpsc::error::SendTimeoutError::Timeout(_) => Self::SendTimeout,
tokio::sync::mpsc::error::SendTimeoutError::Closed(_) => Self::SendTimeout,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_convert_externalerror_to_dferror() {
fn function_return_inner_error() -> Result<(), std::io::Error> {
let inner_error = std::io::Error::new(std::io::ErrorKind::Other, "inner error");
Err(inner_error)
}
fn do_sth_with_error() -> Result<(), DFError> {
function_return_inner_error().map_err(|err| {
ExternalError::new(crate::error::ErrorType::StorageError).with_cause(err.into())
})?;
Ok(())
}
let err = do_sth_with_error().err().unwrap();
assert_eq!(format!("{}", err), "StorageError cause: inner error");
}
}