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