retry_backoff/backoffs/
google_cloud_workflows.rs1#[derive(Debug, Clone, PartialEq)]
3pub struct Backoff {
4 pub initial_delay_secs: f32,
5 pub max_delay_secs: f32,
6 pub multiplier: f32,
7}
8
9impl Default for Backoff {
10 fn default() -> Self {
11 default_backoff()
12 }
13}
14
15pub fn default_backoff() -> Backoff {
17 Backoff::new(1.0, 60.0, 1.25)
18}
19
20impl Backoff {
21 pub fn new(initial_delay_secs: f32, max_delay_secs: f32, multiplier: f32) -> Self {
22 Self {
23 initial_delay_secs,
24 max_delay_secs,
25 multiplier,
26 }
27 }
28
29 #[cfg(feature = "std")]
30 pub fn delay(&self, attempts: usize) -> core::time::Duration {
31 use core::{cmp::min, time::Duration};
32
33 match attempts {
34 0 => unreachable!(),
35 1 => Duration::from_millis((self.initial_delay_secs * 1000.0).round() as u64),
36 n => Duration::from_millis(min(
37 (self.multiplier.powi((n - 1) as i32) * 1000.0).round() as u64,
38 (self.max_delay_secs * 1000.0).round() as u64,
39 )),
40 }
41 }
42}
43
44#[cfg(feature = "std")]
46impl crate::retry_backoff::RetryBackoff for Backoff {
47 fn delay(&self, attempts: usize) -> core::time::Duration {
48 Self::delay(self, attempts)
49 }
50
51 fn name(&self) -> &str {
52 "GoogleCloudWorkflows"
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_default_backoff() {
62 let backoff = default_backoff();
63 assert_eq!(backoff.initial_delay_secs, 1.0);
64 assert_eq!(backoff.max_delay_secs, 60.0);
65 assert_eq!(backoff.multiplier, 1.25);
66
67 assert_eq!(Backoff::default(), default_backoff());
68 }
69
70 #[cfg(feature = "std")]
71 #[test]
72 fn test_delay() {
73 use core::time::Duration;
74
75 let backoff = Backoff::new(1.0, 60.0, 2.0);
77
78 for (attempts, secs) in &[
79 (1, 1),
80 (2, 2),
81 (3, 4),
82 (4, 8),
83 (5, 16),
84 (6, 32),
85 (7, 60),
86 (8, 60),
87 (9, 60),
88 (10, 60),
89 ] {
90 assert_eq!(backoff.delay(*attempts), Duration::from_secs(*secs));
91 }
92 }
93
94 #[cfg(feature = "std")]
95 #[test]
96 fn test_impl_retry_backoff() {
97 use core::time::Duration;
98
99 use crate::retry_backoff::RetryBackoff;
100
101 let backoff = Backoff::new(1.0, 60.0, 2.0);
103
104 for (attempts, secs) in &[
105 (1, 1),
106 (2, 2),
107 (3, 4),
108 (4, 8),
109 (5, 16),
110 (6, 32),
111 (7, 60),
112 (8, 60),
113 (9, 60),
114 (10, 60),
115 ] {
116 assert_eq!(
117 RetryBackoff::delay(&backoff, *attempts),
118 Duration::from_secs(*secs)
119 );
120 }
121 assert_eq!(RetryBackoff::name(&backoff), "GoogleCloudWorkflows");
122 }
123}