@@ -5,7 +5,10 @@ import 'dart:math';
5
5
/// Call the constructor before a loop starts, and call [wait] in each iteration
6
6
/// of the loop. Do not re-use the instance after exiting the loop.
7
7
class BackoffMachine {
8
- BackoffMachine ();
8
+ BackoffMachine ({
9
+ this .firstBound = const Duration (milliseconds: 100 ),
10
+ this .maxBound = const Duration (seconds: 10 ),
11
+ }) : assert (firstBound <= maxBound);
9
12
10
13
/// How many waits have completed so far.
11
14
///
@@ -17,12 +20,12 @@ class BackoffMachine {
17
20
/// The bound on the duration of the first wait.
18
21
///
19
22
/// The actual duration will vary randomly up to this value; see [wait] .
20
- static const firstBound = Duration (milliseconds : 100 ) ;
23
+ final Duration firstBound ;
21
24
22
25
/// The maximum bound on the duration of each wait, even after many waits.
23
26
///
24
27
/// The actual durations will vary randomly up to this value; see [wait] .
25
- static const maxBound = Duration (seconds : 10 ) ;
28
+ final Duration maxBound ;
26
29
27
30
/// The factor the bound is multiplied by at each wait,
28
31
/// until it reaches [maxBound] .
@@ -35,17 +38,20 @@ class BackoffMachine {
35
38
/// A future that resolves after an appropriate backoff time,
36
39
/// with jitter applied to capped exponential growth.
37
40
///
38
- /// A popular exponential backoff strategy is to increase the duration
39
- /// exponentially with the number of sleeps completed, with a base of 2,
40
- /// until a ceiling is reached. E.g., if the first duration is 100ms and
41
- /// the ceiling is 10s = 10000ms, the sequence would be , in ms :
41
+ /// Each [wait] computes an upper bound on its wait duration,
42
+ /// in a sequence growing exponentially from [firstBound]
43
+ /// to a cap of [maxBound] by factors of [base] .
44
+ /// With their default values, this sequence is , in seconds :
42
45
///
43
- /// 100, 200, 400, 800, 1600, 3200, 6400, 10000, 10000, 10000 , ...
46
+ /// 0.1, 0.2, 0.4, 0.8, 1.6, 3.2, 6.4, 10, 10, 10 , ...
44
47
///
45
- /// Instead of using this strategy directly, we also apply "jitter".
46
- /// We use capped exponential backoff for the *upper bound* on a random
47
- /// duration, where the lower bound is always zero. Mitigating "bursts" is
48
- /// the goal of any "jitter" strategy, and the larger the range of randomness,
48
+ /// To provide jitter, the actual wait duration is chosen randomly
49
+ /// on the whole interval from zero up to the computed upper bound.
50
+ ///
51
+ /// This jitter strategy with a lower bound of zero is reported to be more
52
+ /// effective than some widespread strategies that use narrower intervals.
53
+ /// The purpose of jitter is to mitigate "bursts" where many clients make
54
+ /// requests in a short period; the larger the range of randomness,
49
55
/// the smoother the bursts. Keeping the lower bound at zero
50
56
/// maximizes the range while preserving a capped exponential shape on
51
57
/// the expected value. Greg discusses this in more detail at:
0 commit comments