sendWithRetries function
Repeatable calls are retried on a lost connection, 502–504 and 429 with Retry-After. Writes are never retried.
Implementation
Future<http.Response> sendWithRetries(
http.Client client,
http.BaseRequest Function() build, {
required int retries,
required bool retryable,
}) async {
for (var attempt = 0;; attempt++) {
http.Response response;
try {
response = await http.Response.fromStream(await client.send(build()));
} on http.ClientException catch (e) {
if (retryable && attempt < retries) {
await Future<void>.delayed(Duration(milliseconds: 300 * (1 << attempt)));
continue;
}
throw SuperrouteException(status: 0, code: 'network_error', message: 'The request could not reach Superroute. ${e.message}');
}
final retryAfter = response.headers['retry-after'];
final throttled = response.statusCode == 429 && retryAfter != null;
if (retryable && attempt < retries && (_transient(response.statusCode) || throttled)) {
final wait = throttled
? Duration(seconds: min(30, int.tryParse(retryAfter) ?? 1))
: Duration(milliseconds: 300 * (1 << attempt));
await Future<void>.delayed(wait);
continue;
}
return response;
}
}