sendWithRetries function

Future<Response> sendWithRetries(
  1. Client client,
  2. BaseRequest build(), {
  3. required int retries,
  4. required bool retryable,
})

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;
  }
}