pub(crate) struct RetryError<E> {
pub(crate) doing: String,
pub(crate) errors: Vec<(Attempt, E, Instant)>,
pub(crate) n_errors: usize,
pub(crate) first_error_at: Option<SystemTime>,
}Expand description
An error type for use when we’re going to do something a few times, and they might all fail.
To use this error type, initialize a new RetryError before you
start trying to do whatever it is. Then, every time the operation
fails, use RetryError::push() to add a new error to the list
of errors. If the operation fails too many times, you can use
RetryError as an Error itself.
This type now tracks timestamps for each error occurrence, allowing users to see when errors occurred and how long the retry process took.
Fields§
§doing: String§errors: Vec<(Attempt, E, Instant)>§n_errors: usize§first_error_at: Option<SystemTime>Implementations§
Source§impl<E> RetryError<E>
impl<E> RetryError<E>
Sourcepub fn in_attempt_to<T>(doing: T) -> RetryError<E>
pub fn in_attempt_to<T>(doing: T) -> RetryError<E>
Create a new RetryError, with no failed attempts.
The provided doing argument is a short string that describes
what we were trying to do when we failed too many times. It
will be used to format the final error message; it should be a
phrase that can go after “while trying to”.
This RetryError should not be used as-is, since when no
Errors have been pushed into it, it doesn’t represent an
actual failure.
Sourcepub fn push_timed<T>(
&mut self,
err: T,
instant: Instant,
wall_clock: Option<SystemTime>,
)where
T: Into<E>,
pub fn push_timed<T>(
&mut self,
err: T,
instant: Instant,
wall_clock: Option<SystemTime>,
)where
T: Into<E>,
Add an error to this RetryError with explicit timestamps.
You should call this method when an attempt at the underlying operation has failed.
The instant parameter should be the monotonic time when the error
occurred, typically obtained from a runtime’s now() method.
The wall_clock parameter is the wall-clock time when the error occurred,
used for human-readable display. Pass None to skip wall-clock tracking,
or Some(SystemTime::now()) for the current time.
§Example
let mut retry_err: RetryError<&str> = RetryError::in_attempt_to("connect");
let now = Instant::now();
retry_err.push_timed("connection failed", now, Some(SystemTime::now()));Sourcepub fn push<T>(&mut self, err: T)where
T: Into<E>,
pub fn push<T>(&mut self, err: T)where
T: Into<E>,
Add an error to this RetryError using the current time.
You should call this method when an attempt at the underlying operation has failed.
This is a convenience wrapper around push_timed()
that uses Instant::now() and SystemTime::now() for the timestamps.
For code that needs mockable time (such as in tests), prefer push_timed().
Sourcepub fn sources(&self) -> impl Iterator<Item = &E>
pub fn sources(&self) -> impl Iterator<Item = &E>
Return an iterator over all of the reasons that the attempt behind this RetryError has failed.
Sourcepub fn extend<T>(&mut self, iter: impl IntoIterator<Item = T>)where
T: Into<E>,
pub fn extend<T>(&mut self, iter: impl IntoIterator<Item = T>)where
T: Into<E>,
Add multiple errors to this RetryError using the current time.
This method uses push() internally, which captures
SystemTime::now(). For code that needs mockable time (such as in tests),
iterate manually and call push_timed() instead.
§Example
let mut err: RetryError<anyhow::Error> = RetryError::in_attempt_to("parse");
let errors = vec!["error1", "error2"].into_iter().map(anyhow::Error::msg);
err.extend(errors);Sourcepub fn dedup_by<F>(&mut self, same_err: F)
pub fn dedup_by<F>(&mut self, same_err: F)
Group up consecutive errors of the same kind, for easier display.
Two errors have “the same kind” if they return true when passed
to the provided same_err function.
Sourcepub fn extend_from_retry_error(&mut self, other: RetryError<E>)
pub fn extend_from_retry_error(&mut self, other: RetryError<E>)
Add multiple errors to this RetryError, preserving their original timestamps.
The errors from other will be added to this RetryError, with their original
timestamps retained. The Attempt counters will be updated to continue from
the current state of this RetryError. Attempt::Range entries are preserved as ranges
Trait Implementations§
Source§impl<E> Clone for RetryError<E>where
E: Clone,
impl<E> Clone for RetryError<E>where
E: Clone,
Source§fn clone(&self) -> RetryError<E>
fn clone(&self) -> RetryError<E>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl<E> Debug for RetryError<E>where
E: Debug,
impl<E> Debug for RetryError<E>where
E: Debug,
Source§impl<E> Display for RetryError<E>
impl<E> Display for RetryError<E>
Source§impl<E> Error for RetryError<E>
impl<E> Error for RetryError<E>
1.30.0 · Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()
Source§impl<E> From<BackoffError<E>> for RetryError<E>
impl<E> From<BackoffError<E>> for RetryError<E>
Source§fn from(e: BackoffError<E>) -> Self
fn from(e: BackoffError<E>) -> Self
Source§impl<E> IntoIterator for RetryError<E>
impl<E> IntoIterator for RetryError<E>
Auto Trait Implementations§
impl<E> Freeze for RetryError<E>
impl<E> RefUnwindSafe for RetryError<E>where
E: RefUnwindSafe,
impl<E> Send for RetryError<E>where
E: Send,
impl<E> Sync for RetryError<E>where
E: Sync,
impl<E> Unpin for RetryError<E>where
E: Unpin,
impl<E> UnsafeUnpin for RetryError<E>
impl<E> UnwindSafe for RetryError<E>where
E: UnwindSafe,
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, F, I> BatchInvert<F> for I
impl<'a, F, I> BatchInvert<F> for I
Source§fn batch_invert(self) -> F
fn batch_invert(self) -> F
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedSum<usize> for Twhere
T: IntoIterator<Item = usize>,
impl<T> CheckedSum<usize> for Twhere
T: IntoIterator<Item = usize>,
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<E> ErrorReport for Ewhere
E: Error + 'static,
impl<E> ErrorReport for Ewhere
E: Error + 'static,
Source§fn report(&self) -> Report<ReportHelper<'_>>
fn report(&self) -> Report<ReportHelper<'_>>
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PossiblyOption<T> for T
impl<T> PossiblyOption<T> for T
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.