Loading crates/retry-error/src/lib.rs +28 −3 Original line number Diff line number Diff line Loading @@ -127,10 +127,12 @@ impl<E> RetryError<E> { where T: Into<E>, { if self.n_errors < usize::MAX { self.n_errors += 1; let attempt = Attempt::Single(self.n_errors); self.errors.push((attempt, err.into())); } } /// Return an iterator over all of the reasons that the attempt /// behind this RetryError has failed. Loading Loading @@ -329,4 +331,27 @@ Tried to parse some integers 3 times, but all attempts failed. Attempts 1..3: invalid digit found in string" ); } #[test] fn overflow() { use std::num::ParseIntError; let mut err: RetryError<ParseIntError> = RetryError::in_attempt_to("parse too many integers"); assert!(err.is_empty()); let mut errors: Vec<ParseIntError> = vec!["no", "numbers"] .iter() .filter_map(|s| s.parse::<u16>().err()) .collect(); err.n_errors = usize::MAX; err.errors.push(( Attempt::Range(1, err.n_errors), errors.pop().expect("parser did not fail"), )); assert!(err.n_errors == usize::MAX); assert!(err.len() == 1); err.push(errors.pop().expect("parser did not fail")); assert!(err.n_errors == usize::MAX); assert!(err.len() == 1); } } crates/tor-error/src/retriable.rs +27 −4 Original line number Diff line number Diff line Loading @@ -161,8 +161,14 @@ impl RetryTime { { match self { RetryTime::Immediate => AbsRetryTime::Immediate, RetryTime::AfterWaiting => AbsRetryTime::At(now + choose_delay()), RetryTime::After(d) => AbsRetryTime::At(now + d), RetryTime::AfterWaiting => match now.checked_add(choose_delay()) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }, RetryTime::After(d) => match now.checked_add(d) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }, RetryTime::At(t) => AbsRetryTime::At(t), RetryTime::Never => AbsRetryTime::Never, } Loading @@ -181,11 +187,14 @@ impl RetryTime { I: Iterator<Item = RetryTime>, F: FnOnce() -> Duration, { let chosen_delay = once_cell::unsync::Lazy::new(choose_delay); let chosen_delay = once_cell::unsync::Lazy::new(|| match now.checked_add(choose_delay()) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }); items .map(|item| match item { RetryTime::AfterWaiting => AbsRetryTime::At(now + *chosen_delay), RetryTime::AfterWaiting => *chosen_delay, other => other.absolute(now, || unreachable!()), }) .min() Loading Loading @@ -277,4 +286,18 @@ mod test { } } } #[test] fn earliest_absolute() { let sec = Duration::from_secs(1); let now = Instant::now(); let times = vec![RetryTime::AfterWaiting, RetryTime::Never]; let earliest = RetryTime::earliest_absolute(times.into_iter(), now, || sec); assert_eq!( earliest.expect("no absolute time"), AbsRetryTime::At(now + sec) ); } } Loading
crates/retry-error/src/lib.rs +28 −3 Original line number Diff line number Diff line Loading @@ -127,10 +127,12 @@ impl<E> RetryError<E> { where T: Into<E>, { if self.n_errors < usize::MAX { self.n_errors += 1; let attempt = Attempt::Single(self.n_errors); self.errors.push((attempt, err.into())); } } /// Return an iterator over all of the reasons that the attempt /// behind this RetryError has failed. Loading Loading @@ -329,4 +331,27 @@ Tried to parse some integers 3 times, but all attempts failed. Attempts 1..3: invalid digit found in string" ); } #[test] fn overflow() { use std::num::ParseIntError; let mut err: RetryError<ParseIntError> = RetryError::in_attempt_to("parse too many integers"); assert!(err.is_empty()); let mut errors: Vec<ParseIntError> = vec!["no", "numbers"] .iter() .filter_map(|s| s.parse::<u16>().err()) .collect(); err.n_errors = usize::MAX; err.errors.push(( Attempt::Range(1, err.n_errors), errors.pop().expect("parser did not fail"), )); assert!(err.n_errors == usize::MAX); assert!(err.len() == 1); err.push(errors.pop().expect("parser did not fail")); assert!(err.n_errors == usize::MAX); assert!(err.len() == 1); } }
crates/tor-error/src/retriable.rs +27 −4 Original line number Diff line number Diff line Loading @@ -161,8 +161,14 @@ impl RetryTime { { match self { RetryTime::Immediate => AbsRetryTime::Immediate, RetryTime::AfterWaiting => AbsRetryTime::At(now + choose_delay()), RetryTime::After(d) => AbsRetryTime::At(now + d), RetryTime::AfterWaiting => match now.checked_add(choose_delay()) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }, RetryTime::After(d) => match now.checked_add(d) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }, RetryTime::At(t) => AbsRetryTime::At(t), RetryTime::Never => AbsRetryTime::Never, } Loading @@ -181,11 +187,14 @@ impl RetryTime { I: Iterator<Item = RetryTime>, F: FnOnce() -> Duration, { let chosen_delay = once_cell::unsync::Lazy::new(choose_delay); let chosen_delay = once_cell::unsync::Lazy::new(|| match now.checked_add(choose_delay()) { Some(t) => AbsRetryTime::At(t), None => AbsRetryTime::Never, }); items .map(|item| match item { RetryTime::AfterWaiting => AbsRetryTime::At(now + *chosen_delay), RetryTime::AfterWaiting => *chosen_delay, other => other.absolute(now, || unreachable!()), }) .min() Loading Loading @@ -277,4 +286,18 @@ mod test { } } } #[test] fn earliest_absolute() { let sec = Duration::from_secs(1); let now = Instant::now(); let times = vec![RetryTime::AfterWaiting, RetryTime::Never]; let earliest = RetryTime::earliest_absolute(times.into_iter(), now, || sec); assert_eq!( earliest.expect("no absolute time"), AbsRetryTime::At(now + sec) ); } }