Skip to content

Commit

Permalink
Merge pull request #1815 from EliahKagan/quadratic
Browse files Browse the repository at this point in the history
Rename `Exponential` backoff to `Quadratic`
  • Loading branch information
Byron authored Jan 27, 2025
2 parents 99c2706 + 6990f76 commit ffb73b5
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 18 deletions.
4 changes: 2 additions & 2 deletions gix-lock/src/acquire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub enum Fail {
/// Fail after the first unsuccessful attempt of obtaining a lock.
#[default]
Immediately,
/// Retry after failure with exponentially longer sleep times to block the current thread.
/// Retry after failure with quadratically longer sleep times to block the current thread.
/// Fail once the given duration is exceeded, similar to [Fail::Immediately]
AfterDurationWithBackoff(Duration),
}
Expand Down Expand Up @@ -176,7 +176,7 @@ fn lock_with_mode<T>(
match mode {
Fail::Immediately => try_lock(&lock_path, directory, cleanup),
Fail::AfterDurationWithBackoff(time) => {
for wait in backoff::Exponential::default_with_random().until_no_remaining(time) {
for wait in backoff::Quadratic::default_with_random().until_no_remaining(time) {
attempts += 1;
match try_lock(&lock_path, directory, cleanup.clone()) {
Ok(v) => return Ok((lock_path, v)),
Expand Down
18 changes: 9 additions & 9 deletions gix-utils/src/backoff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ fn randomize(backoff_ms: usize) -> usize {
}
}

/// A utility to calculate steps for exponential backoff similar to how it's done in `git`.
pub struct Exponential<Fn> {
/// A utility to calculate steps for quadratic backoff similar to how it's done in `git`.
pub struct Quadratic<Fn> {
multiplier: usize,
max_multiplier: usize,
exponent: usize,
transform: Fn,
}

impl Default for Exponential<fn(usize) -> usize> {
impl Default for Quadratic<fn(usize) -> usize> {
fn default() -> Self {
Exponential {
Quadratic {
multiplier: 1,
max_multiplier: 1000,
exponent: 1,
Expand All @@ -28,10 +28,10 @@ impl Default for Exponential<fn(usize) -> usize> {
}
}

impl Exponential<fn(usize) -> usize> {
/// Create a new exponential backoff iterator that backs off in randomized, ever increasing steps.
impl Quadratic<fn(usize) -> usize> {
/// Create a new quadratic backoff iterator that backs off in randomized, ever increasing steps.
pub fn default_with_random() -> Self {
Exponential {
Quadratic {
multiplier: 1,
max_multiplier: 1000,
exponent: 1,
Expand All @@ -40,7 +40,7 @@ impl Exponential<fn(usize) -> usize> {
}
}

impl<Transform> Exponential<Transform>
impl<Transform> Quadratic<Transform>
where
Transform: Fn(usize) -> usize,
{
Expand All @@ -62,7 +62,7 @@ where
}
}

impl<Transform> Iterator for Exponential<Transform>
impl<Transform> Iterator for Quadratic<Transform>
where
Transform: Fn(usize) -> usize,
{
Expand Down
12 changes: 6 additions & 6 deletions gix-utils/tests/backoff/mod.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use std::time::Duration;

use gix_utils::backoff::Exponential;
use gix_utils::backoff::Quadratic;

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() {
fn random_quadratic_produces_values_in_the_correct_range() {
let mut num_identities = 0;
for (actual, expected) in Exponential::default_with_random().zip(EXPECTED_TILL_SECOND) {
for (actual, expected) in Quadratic::default_with_random().zip(EXPECTED_TILL_SECOND) {
let actual: usize = actual.as_millis().try_into().unwrap();
if actual == *expected {
num_identities += 1;
Expand All @@ -33,9 +33,9 @@ fn random_exponential_produces_values_in_the_correct_range() {
#[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!(Quadratic::default().until_no_remaining(max).count(), 14);
assert_eq!(
Exponential::default()
Quadratic::default()
.until_no_remaining(max)
.reduce(|acc, n| acc + n)
.unwrap(),
Expand All @@ -47,7 +47,7 @@ fn how_many_iterations_for_a_second_of_waittime() {
#[test]
fn output_with_default_settings() {
assert_eq!(
Exponential::default().take(33).collect::<Vec<_>>(),
Quadratic::default().take(33).collect::<Vec<_>>(),
EXPECTED_TILL_SECOND
.iter()
.map(|n| Duration::from_millis(*n as u64))
Expand Down
3 changes: 2 additions & 1 deletion tests/tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ pub fn spawn_git_daemon(working_dir: impl AsRef<Path>) -> std::io::Result<GitDae
.spawn()?;

let server_addr = addr_at(free_port);
// TODO(deps): Upgrading dependencies will require changing `Exponential` to `Quadratic`.
for time in gix_lock::backoff::Exponential::default_with_random() {
std::thread::sleep(time);
if std::net::TcpStream::connect(server_addr).is_ok() {
Expand Down Expand Up @@ -652,8 +653,8 @@ fn configure_command<'a, I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
}

fn bash_program() -> &'static Path {
// TODO: use `gix_path::env::login_shell()` when available.
if cfg!(windows) {
// TODO(deps): Once `gix_path::env::shell()` is available, maybe do `shell().parent()?.join("bash.exe")`
static GIT_BASH: Lazy<Option<PathBuf>> = Lazy::new(|| {
GIT_CORE_DIR
.parent()?
Expand Down

0 comments on commit ffb73b5

Please sign in to comment.