diff options
Diffstat (limited to 'vendor/gix-lock/src/backoff.rs')
-rw-r--r-- | vendor/gix-lock/src/backoff.rs | 142 |
1 files changed, 0 insertions, 142 deletions
diff --git a/vendor/gix-lock/src/backoff.rs b/vendor/gix-lock/src/backoff.rs deleted file mode 100644 index f1c3559a6..000000000 --- a/vendor/gix-lock/src/backoff.rs +++ /dev/null @@ -1,142 +0,0 @@ -use std::time::Duration; - -fn randomize(backoff_ms: usize) -> usize { - let new_value = (fastrand::usize(750..=1250) * backoff_ms) / 1000; - if new_value == 0 { - backoff_ms - } else { - new_value - } -} - -/// A utility to calculate steps for exponential backoff similar to how it's done in `git`. -pub struct Exponential<Fn> { - multiplier: usize, - max_multiplier: usize, - exponent: usize, - transform: Fn, -} - -impl Default for Exponential<fn(usize) -> usize> { - fn default() -> Self { - Exponential { - multiplier: 1, - max_multiplier: 1000, - exponent: 1, - transform: std::convert::identity, - } - } -} - -impl Exponential<fn(usize) -> usize> { - /// Create a new exponential backoff iterator that backs off in randomized, ever increasing steps. - pub fn default_with_random() -> Self { - Exponential { - multiplier: 1, - max_multiplier: 1000, - exponent: 1, - transform: randomize, - } - } -} - -impl<Transform> Exponential<Transform> -where - Transform: Fn(usize) -> usize, -{ - /// Return an iterator that yields `Duration` instances to sleep on until `time` is depleted. - pub fn until_no_remaining(&mut self, time: Duration) -> impl Iterator<Item = Duration> + '_ { - let mut elapsed = Duration::default(); - let mut stop_next_iteration = false; - self.take_while(move |d| { - if stop_next_iteration { - false - } else { - elapsed += *d; - if elapsed > time { - stop_next_iteration = true; - } - true - } - }) - } -} - -impl<Transform> Iterator for Exponential<Transform> -where - Transform: Fn(usize) -> usize, -{ - type Item = Duration; - - fn next(&mut self) -> Option<Self::Item> { - let wait = Duration::from_millis((self.transform)(self.multiplier) as u64); - - self.multiplier += 2 * self.exponent + 1; - if self.multiplier > self.max_multiplier { - self.multiplier = self.max_multiplier; - } else { - self.exponent += 1; - } - Some(wait) - } -} - -#[cfg(test)] -mod tests { - use std::convert::TryInto; - - use super::*; - - const EXPECTED_TILL_SECOND: &[usize] = &[ - 1usize, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, - 576, 625, 676, 729, 784, 841, 900, 961, 1000, 1000, - ]; - - #[test] - fn random_exponential_produces_values_in_the_correct_range() { - let mut num_identities = 0; - for (actual, expected) in Exponential::default_with_random().zip(EXPECTED_TILL_SECOND) { - let actual: usize = actual.as_millis().try_into().unwrap(); - if actual == *expected { - num_identities += 1; - } - assert!( - actual * 1000 >= (expected - 1) * 750, - "value too small: {actual} < {expected}" - ); - assert!( - actual * 1000 <= (expected + 1) * 1250, - "value too big: {actual} > {expected}" - ); - } - assert!( - num_identities < EXPECTED_TILL_SECOND.len(), - "too many untransformed values: {num_identities}" - ); - } - - #[test] - fn how_many_iterations_for_a_second_of_waittime() { - let max = Duration::from_millis(1000); - assert_eq!(Exponential::default().until_no_remaining(max).count(), 14); - assert_eq!( - Exponential::default() - .until_no_remaining(max) - .reduce(|acc, n| acc + n) - .unwrap(), - Duration::from_millis(1015), - "a little overshoot" - ); - } - - #[test] - fn output_with_default_settings() { - assert_eq!( - Exponential::default().take(33).collect::<Vec<_>>(), - EXPECTED_TILL_SECOND - .iter() - .map(|n| Duration::from_millis(*n as u64)) - .collect::<Vec<_>>() - ); - } -} |