@@ -17,11 +17,14 @@ class RetryClient extends BaseClient {
17
17
final int _retries;
18
18
19
19
/// The callback that determines whether a request should be retried.
20
- final bool Function (StreamedResponse ) _when;
20
+ final bool Function (BaseResponse ) _when;
21
21
22
22
/// The callback that determines how long to wait before retrying a request.
23
23
final Duration Function (int ) _delay;
24
24
25
+ /// The callback to call to indicate that a request is being retried.
26
+ final void Function (BaseRequest , BaseResponse , int ) _onRetry;
27
+
25
28
/// Creates a client wrapping [inner] that retries HTTP requests.
26
29
///
27
30
/// This retries a failing request [retries] times (3 by default). Note that
@@ -35,15 +38,20 @@ class RetryClient extends BaseClient {
35
38
/// retry, then increases the delay by 1.5x for each subsequent retry. If
36
39
/// [delay] is passed, it's used to determine the time to wait before the
37
40
/// given (zero-based) retry.
41
+ ///
42
+ /// If [onRetry] is passed, it's called immediately before each retry so that
43
+ /// the client has a chance to perform side effects like logging.
38
44
RetryClient (this ._inner,
39
45
{int retries,
40
- bool when (StreamedResponse response),
41
- Duration delay (int retryCount)})
46
+ bool when (BaseResponse response),
47
+ Duration delay (int retryCount),
48
+ void onRetry (BaseRequest request, BaseResponse response, int retryCount)})
42
49
: _retries = retries ?? 3 ,
43
50
_when = when ?? ((response) => response.statusCode == 503 ),
44
51
_delay = delay ??
45
52
((retryCount) =>
46
- new Duration (milliseconds: 500 ) * math.pow (1.5 , retryCount)) {
53
+ new Duration (milliseconds: 500 ) * math.pow (1.5 , retryCount)),
54
+ _onRetry = onRetry {
47
55
RangeError .checkNotNegative (_retries, "retries" );
48
56
}
49
57
@@ -54,13 +62,18 @@ class RetryClient extends BaseClient {
54
62
/// in order. It will wait for `delays[0]` after the initial request,
55
63
/// `delays[1]` after the first retry, and so on.
56
64
RetryClient .withDelays (Client inner, Iterable <Duration > delays,
57
- {bool when (StreamedResponse response)})
58
- : this ._withDelays (inner, delays.toList (), when : when );
65
+ {bool when (BaseResponse response),
66
+ void onRetry (BaseRequest request, BaseResponse response, int retryCount)})
67
+ : this ._withDelays (inner, delays.toList (), when : when , onRetry: onRetry);
59
68
60
69
RetryClient ._withDelays (Client inner, List <Duration > delays,
61
- {bool when (StreamedResponse response)})
70
+ {bool when (BaseResponse response),
71
+ void onRetry (BaseRequest request, BaseResponse response, int retryCount)})
62
72
: this (inner,
63
- retries: delays.length, delay: (retryCount) => delays[retryCount]);
73
+ retries: delays.length,
74
+ delay: (retryCount) => delays[retryCount],
75
+ when : when ,
76
+ onRetry: onRetry);
64
77
65
78
Future <StreamedResponse > send (BaseRequest request) async {
66
79
var splitter = new StreamSplitter (request.finalize ());
@@ -74,6 +87,7 @@ class RetryClient extends BaseClient {
74
87
// dangling connections.
75
88
response.stream.listen ((_) {}).cancel ()? .catchError ((_) {});
76
89
await new Future .delayed (_delay (i));
90
+ if (_onRetry != null ) _onRetry (request, response, i);
77
91
i++ ;
78
92
}
79
93
}
0 commit comments