Created
November 16, 2023 14:29
-
-
Save ulusoyca/200e4c7c1cf118e2e923936abfe1fa96 to your computer and use it in GitHub Desktop.
An example for using retry policy with dart http package
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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