1+ use rand:: Rng ;
12use std:: error:: Error ;
23use std:: future:: Future ;
34use std:: marker:: PhantomData ;
@@ -21,7 +22,8 @@ use std::time::Duration;
2122/// #
2223/// let retry_policy = ExponentialBackoffRetryPolicy::new(Duration::from_millis(100))
2324/// .with_max_attempts(5)
24- /// .with_max_total_delay(Duration::from_secs(2));
25+ /// .with_max_total_delay(Duration::from_secs(2))
26+ /// .with_max_jitter(Duration::from_millis(30));
2527///
2628/// let result = retry(operation, &retry_policy);
2729///```
@@ -72,6 +74,11 @@ pub trait RetryPolicy: Sized {
7274 fn with_max_total_delay ( self , max_total_delay : Duration ) -> MaxTotalDelayRetryPolicy < Self > {
7375 MaxTotalDelayRetryPolicy { inner_policy : self , max_total_delay }
7476 }
77+
78+ /// Returns a new `RetryPolicy` that adds jitter(random delay) to underlying policy.
79+ fn with_max_jitter ( self , max_jitter : Duration ) -> JitteredRetryPolicy < Self > {
80+ JitteredRetryPolicy { inner_policy : self , max_jitter }
81+ }
7582}
7683
7784/// Represents the context of a retry operation.
@@ -157,4 +164,26 @@ impl<T: RetryPolicy> RetryPolicy for MaxTotalDelayRetryPolicy<T> {
157164 }
158165 next_delay
159166 }
160- }
167+ }
168+
169+ /// Decorates the given `RetryPolicy` and adds jitter (random delay) to it. This can make retries
170+ /// more spread out and less likely to all fail at once.
171+ pub struct JitteredRetryPolicy < T : RetryPolicy > {
172+ /// The underlying retry policy to use.
173+ inner_policy : T ,
174+ /// The maximum amount of random jitter to apply to the delay.
175+ max_jitter : Duration ,
176+ }
177+
178+ impl < T : RetryPolicy > RetryPolicy for JitteredRetryPolicy < T > {
179+ type E = T :: E ;
180+ fn next_delay ( & self , context : & RetryContext < Self :: E > ) -> Option < Duration > {
181+ if let Some ( base_delay) = self . inner_policy . next_delay ( context) {
182+ let mut rng = rand:: thread_rng ( ) ;
183+ let jitter = Duration :: from_micros ( rng. gen_range ( 0 ..self . max_jitter . as_micros ( ) as u64 ) ) ;
184+ Some ( base_delay + jitter)
185+ } else {
186+ None
187+ }
188+ }
189+ }
0 commit comments