use remora_stream::{StreamError, StreamSide}; use remora_target::TargetError; #[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)] pub enum ObjectSourceError { #[error("object source request is invalid")] InvalidRequest, #[error("object source access is denied")] SourceAuthorization, #[error("destination access is denied")] DestinationAuthorization, #[error("object source was not found")] SourceNotFound, #[error("object source changed")] SourceChanged, #[error("destination resume state changed")] DestinationChanged, #[error("object source is temporarily unavailable")] TransientSource, #[error("destination is temporarily unavailable")] TransientDestination, #[error("object source adapter failed")] Internal, } impl ObjectSourceError { #[must_use] pub fn into_stream_error(self) -> StreamError { match self { Self::SourceAuthorization => StreamError::Authorization { side: StreamSide::Source, }, Self::DestinationAuthorization => StreamError::Authorization { side: StreamSide::Target, }, Self::SourceNotFound => StreamError::SourceNotFound, Self::SourceChanged => StreamError::SourceChanged, Self::TransientSource => StreamError::transient_source("object source unavailable"), Self::TransientDestination => StreamError::transient_target("destination unavailable"), Self::DestinationChanged => { StreamError::internal("destination resume proof is no longer reusable") } Self::InvalidRequest | Self::Internal => { StreamError::internal("object source contract violation") } } } } pub(crate) fn map_open_error(error: opendal::Error) -> ObjectSourceError { use opendal::ErrorKind; match error.kind() { ErrorKind::NotFound => ObjectSourceError::SourceNotFound, ErrorKind::PermissionDenied => ObjectSourceError::SourceAuthorization, ErrorKind::ConditionNotMatch | ErrorKind::RangeNotSatisfied => { ObjectSourceError::SourceChanged } ErrorKind::RateLimited => ObjectSourceError::TransientSource, ErrorKind::Unsupported | ErrorKind::ConfigInvalid => ObjectSourceError::InvalidRequest, _ => ObjectSourceError::TransientSource, } } pub(crate) fn map_resume_error(error: opendal::Error) -> ObjectSourceError { match map_open_error(error) { ObjectSourceError::SourceNotFound => ObjectSourceError::SourceChanged, other => other, } } pub(crate) fn map_destination_error(error: TargetError) -> ObjectSourceError { match error { TargetError::Authorization => ObjectSourceError::DestinationAuthorization, TargetError::NotFound | TargetError::AlreadyExists | TargetError::Integrity(_) => { ObjectSourceError::DestinationChanged } TargetError::Capacity | TargetError::Transient(_) => { ObjectSourceError::TransientDestination } TargetError::Validation(_) | TargetError::Internal(_) => ObjectSourceError::Internal, } }