Skip to content

Commit

Permalink
Refactor builders to be const
Browse files Browse the repository at this point in the history
- Refactored all methods inside FibonacciBuilder, ExponentialBuilder, and ConstantBuilder to be const.
- Added a new const `new` constructor for each builder which uses the values from default()
- Updated the default method to call `new()`.
- Added unit tests for the const builders to ensure they have the correct values.
  • Loading branch information
Matt3o12 committed Dec 17, 2024
1 parent c574c61 commit 468b8fd
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 25 deletions.
17 changes: 11 additions & 6 deletions backon/src/backoff/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,36 @@ pub struct ConstantBuilder {

impl Default for ConstantBuilder {
fn default() -> Self {
Self::new()
}
}

impl ConstantBuilder {
/// Create a new `ConstantBuilder` with default values.
pub const fn new() -> Self {
Self {
delay: Duration::from_secs(1),
max_times: Some(3),
jitter: false,
}
}
}

impl ConstantBuilder {
/// Set the delay for the backoff.
pub fn with_delay(mut self, delay: Duration) -> Self {
pub const fn with_delay(mut self, delay: Duration) -> Self {
self.delay = delay;
self
}

/// Set the maximum number of attempts to be made.
pub fn with_max_times(mut self, max_times: usize) -> Self {
pub const fn with_max_times(mut self, max_times: usize) -> Self {
self.max_times = Some(max_times);
self
}

/// Set jitter for the backoff.
///
/// Jitter is a random value added to the delay to prevent a thundering herd problem.
pub fn with_jitter(mut self) -> Self {
pub const fn with_jitter(mut self) -> Self {
self.jitter = true;
self
}
Expand All @@ -74,7 +79,7 @@ impl ConstantBuilder {
/// The backoff will not stop by itself.
///
/// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._
pub fn without_max_times(mut self) -> Self {
pub const fn without_max_times(mut self) -> Self {
self.max_times = None;
self
}
Expand Down
39 changes: 30 additions & 9 deletions backon/src/backoff/exponential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ pub struct ExponentialBuilder {

impl Default for ExponentialBuilder {
fn default() -> Self {
Self::new()
}
}

impl ExponentialBuilder {
/// Create a new `ExponentialBuilder` with default values.
pub const fn new() -> Self {
Self {
jitter: false,
factor: 2.0,
Expand All @@ -53,14 +60,12 @@ impl Default for ExponentialBuilder {
max_times: Some(3),
}
}
}

impl ExponentialBuilder {
/// Set the jitter for the backoff.
///
/// When jitter is enabled, [`ExponentialBackoff`] will add a random jitter within `(0, min_delay)`
/// to the current delay.
pub fn with_jitter(mut self) -> Self {
pub const fn with_jitter(mut self) -> Self {
self.jitter = true;
self
}
Expand All @@ -70,23 +75,23 @@ impl ExponentialBuilder {
/// # Panics
///
/// This function will panic if the input factor is less than `1.0`.
pub fn with_factor(mut self, factor: f32) -> Self {
pub const fn with_factor(mut self, factor: f32) -> Self {
debug_assert!(factor >= 1.0, "invalid factor that lower than 1");

self.factor = factor;
self
}

/// Set the minimum delay for the backoff.
pub fn with_min_delay(mut self, min_delay: Duration) -> Self {
pub const fn with_min_delay(mut self, min_delay: Duration) -> Self {
self.min_delay = min_delay;
self
}

/// Set the maximum delay for the backoff.
///
/// The delay will not increase if the current delay exceeds the maximum delay.
pub fn with_max_delay(mut self, max_delay: Duration) -> Self {
pub const fn with_max_delay(mut self, max_delay: Duration) -> Self {
self.max_delay = Some(max_delay);
self
}
Expand All @@ -96,15 +101,15 @@ impl ExponentialBuilder {
/// The delay will keep increasing.
///
/// _The delay will saturate at `Duration::MAX` which is an **unrealistic** delay._
pub fn without_max_delay(mut self) -> Self {
pub const fn without_max_delay(mut self) -> Self {
self.max_delay = None;
self
}

/// Set the maximum number of attempts for the current backoff.
///
/// The backoff will stop if the maximum number of attempts is reached.
pub fn with_max_times(mut self, max_times: usize) -> Self {
pub const fn with_max_times(mut self, max_times: usize) -> Self {
self.max_times = Some(max_times);
self
}
Expand All @@ -114,7 +119,7 @@ impl ExponentialBuilder {
/// The backoff will not stop by itself.
///
/// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._
pub fn without_max_times(mut self) -> Self {
pub const fn without_max_times(mut self) -> Self {
self.max_times = None;
self
}
Expand Down Expand Up @@ -215,6 +220,13 @@ mod tests {
use crate::BackoffBuilder;
use crate::ExponentialBuilder;

const TEST_BUILDER: ExponentialBuilder = ExponentialBuilder::new()
.with_jitter()
.with_factor(1.5)
.with_min_delay(Duration::from_secs(2))
.with_max_delay(Duration::from_secs(30))
.with_max_times(5);

#[test]
fn test_exponential_default() {
let mut exp = ExponentialBuilder::default().build();
Expand Down Expand Up @@ -366,4 +378,13 @@ mod tests {
assert_eq!(Some(Duration::from_secs(1)), exp.next());
assert_eq!(None, exp.next());
}

#[test]
fn test_exponential_const_builder() {
assert!(TEST_BUILDER.jitter);
assert_eq!(TEST_BUILDER.factor, 1.5);
assert_eq!(TEST_BUILDER.min_delay, Duration::from_secs(2));
assert_eq!(TEST_BUILDER.max_delay, Some(Duration::from_secs(30)));
assert_eq!(TEST_BUILDER.max_times, Some(5));
}
}
37 changes: 27 additions & 10 deletions backon/src/backoff/fibonacci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,34 +43,39 @@ pub struct FibonacciBuilder {

impl Default for FibonacciBuilder {
fn default() -> Self {
Self::new()
}
}

impl FibonacciBuilder {
/// Create a new `FibonacciBuilder` with default values.
pub const fn new() -> Self {
Self {
jitter: false,
min_delay: Duration::from_secs(1),
max_delay: Some(Duration::from_secs(60)),
max_times: Some(3),
}
}
}

impl FibonacciBuilder {
/// Set the jitter for the backoff.
///
/// When jitter is enabled, FibonacciBackoff will add a random jitter between `(0, min_delay)` to the delay.
pub fn with_jitter(mut self) -> Self {
pub const fn with_jitter(mut self) -> Self {
self.jitter = true;
self
}

/// Set the minimum delay for the backoff.
pub fn with_min_delay(mut self, min_delay: Duration) -> Self {
pub const fn with_min_delay(mut self, min_delay: Duration) -> Self {
self.min_delay = min_delay;
self
}

/// Set the maximum delay for the current backoff.
///
/// The delay will not increase if the current delay exceeds the maximum delay.
pub fn with_max_delay(mut self, max_delay: Duration) -> Self {
pub const fn with_max_delay(mut self, max_delay: Duration) -> Self {
self.max_delay = Some(max_delay);
self
}
Expand All @@ -80,15 +85,15 @@ impl FibonacciBuilder {
/// The delay will keep increasing.
///
/// _The delay will saturate at `Duration::MAX` which is an **unrealistic** delay._
pub fn without_max_delay(mut self) -> Self {
pub const fn without_max_delay(mut self) -> Self {
self.max_delay = None;
self
}

/// Set the maximum number of attempts for the current backoff.
///
/// The backoff will stop if the maximum number of attempts is reached.
pub fn with_max_times(mut self, max_times: usize) -> Self {
pub const fn with_max_times(mut self, max_times: usize) -> Self {
self.max_times = Some(max_times);
self
}
Expand All @@ -98,7 +103,7 @@ impl FibonacciBuilder {
/// The backoff will not stop by itself.
///
/// _The backoff could stop reaching `usize::MAX` attempts but this is **unrealistic**._
pub fn without_max_times(mut self) -> Self {
pub const fn without_max_times(mut self) -> Self {
self.max_times = None;
self
}
Expand Down Expand Up @@ -192,13 +197,17 @@ impl Iterator for FibonacciBackoff {

#[cfg(test)]
mod tests {
use super::*;
use core::time::Duration;

#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;

use crate::BackoffBuilder;
use crate::FibonacciBuilder;
const TEST_BUILDER: FibonacciBuilder = FibonacciBuilder::new()
.with_jitter()
.with_min_delay(Duration::from_secs(2))
.with_max_delay(Duration::from_secs(30))
.with_max_times(5);

#[test]
fn test_fibonacci_default() {
Expand Down Expand Up @@ -302,4 +311,12 @@ mod tests {
assert_eq!(Some(Duration::from_secs(0)), fib.next());
}
}

#[test]
fn test_fibonacci_const_builder() {
assert!(TEST_BUILDER.jitter);
assert_eq!(TEST_BUILDER.min_delay, Duration::from_secs(2));
assert_eq!(TEST_BUILDER.max_delay, Some(Duration::from_secs(30)));
assert_eq!(TEST_BUILDER.max_times, Some(5));
}
}

0 comments on commit 468b8fd

Please sign in to comment.