Skip to content

Instantly share code, notes, and snippets.

@ulusoyca
Created November 16, 2023 14:29
Show Gist options
  • Save ulusoyca/200e4c7c1cf118e2e923936abfe1fa96 to your computer and use it in GitHub Desktop.
Save ulusoyca/200e4c7c1cf118e2e923936abfe1fa96 to your computer and use it in GitHub Desktop.
An example for using retry policy with dart http package
import 'dart:async';
import 'dart:math';
import 'package:http/http.dart' as http;
/// A utility class for generating a list of waiting times (delays) for HTTP request retries.
/// This class uses an exponential backoff strategy with jitter for calculating delay times.
class HttpRetryDurationListGenerator {
/// Generates a list of waiting times (durations) to be used between retry attempts.
///
/// This method calculates delay times based on exponential backoff strategy, which gradually increases
/// the delay between retry attempts, helping to reduce the load on the server and increase the
/// probability of a successful response in case of transient server issues.
///
/// Parameters:
/// - `maxRetryCount`: The maximum number of retries for which to generate delay times.
/// - `baseDelay`: The initial delay time before the first retry attempt.
/// - `maxDelay`: The maximum allowable delay time. No calculated delay will exceed this value.
/// - `backoffFactor`: The factor by which the delay time is multiplied for each subsequent retry.
///
/// Returns a list of `Duration` objects representing the delay times for each retry attempt.
static List<Duration> generateWaitingTimes({
required int maxRetryCount,
required Duration baseDelay,
required Duration maxDelay,
required double backoffFactor,
}) {
assert(maxDelay >= baseDelay, 'maxDelay should be greater than or equal to baseDelay');
final List<Duration> waitingTimes = [];
Duration currentDelay = baseDelay;
for (var i = 0; i < maxRetryCount; i++) {
// Add the current delay to the list of waiting times.
waitingTimes.add(currentDelay);
currentDelay = _calculateNextDelay(
backoffFactor: backoffFactor,
currentDelay: currentDelay,
maxDelay: maxDelay,
);
}
return waitingTimes;
}
/// A private helper method to calculate the delay for the next retry attempt.
///
/// This method applies the exponential backoff algorithm, which multiplies the current delay
/// by the backoff factor, and adds a randomized jitter. The jitter helps to avoid the scenario
/// where many clients retry simultaneously, causing spikes in load on the server.
///
/// Parameters:
/// - `currentDelay`: The delay used in the last retry attempt.
/// - `backoffFactor`: The factor by which to multiply the current delay.
/// - `maxDelay`: The maximum allowable delay.
///
/// Returns the calculated delay for the next retry attempt, ensuring it doesn't exceed `maxDelay`.
static Duration _calculateNextDelay({
required Duration currentDelay,
required double backoffFactor,
required Duration maxDelay,
}) {
// Calculates the jitter, which adds randomness to the delay times.
// The jitter is a random duration up to one second, which helps in distributing
// retry attempts over time when multiple clients are involved.
final jitter = Duration(milliseconds: Random().nextInt(1000));
// Calculate the next delay time by multiplying the current delay by the backoff factor
// and adding the jitter. The resulting delay is compared with `maxDelay` to ensure it
// doesn't exceed the maximum allowed delay.
final nextDelay = (currentDelay * backoffFactor) + jitter;
// Ensure the next delay doesn't exceed the maximum delay.
return nextDelay < maxDelay ? nextDelay : maxDelay;
}
}
RetryClient.withDelays(
http.Client(),
WoltHttpRetryDurationListGenerator.generateWaitingTimes(
maxRetryCount: 3,
baseDelay: const Duration(seconds: 1),
maxDelay: const Duration(seconds: 15),
backoffFactor: 2,
),
when: (response) => response.statusCode >= 500 && response.statusCode == 429,
onRetry: (request, response, retryCount) {
Randall.d(
'Retrying request ${request.url}\nresponse code: ${response?.statusCode}\nretry count: $retryCount',
);
},
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment