Skip to content

Instantly share code, notes, and snippets.

@hyrmn
Last active August 1, 2023 09:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyrmn/a5227ed08923f3d14bab7736a9683c24 to your computer and use it in GitHub Desktop.
Save hyrmn/a5227ed08923f3d14bab7736a9683c24 to your computer and use it in GitHub Desktop.
Polly.Contrib.WaitAndRetry examples
var transientErrors = new HashSet<WebExceptionStatus>(new[]
{
WebExceptionStatus.ConnectFailure,
WebExceptionStatus.ConnectionClosed,
WebExceptionStatus.KeepAliveFailure,
WebExceptionStatus.Pending,
WebExceptionStatus.PipelineFailure,
WebExceptionStatus.ProtocolError,
WebExceptionStatus.ReceiveFailure,
WebExceptionStatus.RequestCanceled,
WebExceptionStatus.SecureChannelFailure,
WebExceptionStatus.SendFailure,
WebExceptionStatus.Timeout
});
var retryTimes = new List<TimeSpan>
{
TimeSpan.FromMilliseconds(0),
TimeSpan.FromMilliseconds(50),
TimeSpan.FromMilliseconds(100),
TimeSpan.FromMilliseconds(150)
};
var retryPolicy = Policy
.Handle<WebException>(ex => transientErrors.Contains(ex.Status))
.OrInner<WebException>(ex => transientErrors.Contains(ex.Status))
.Or<TimeoutException>()
.OrInner<TimeoutException>()
.WaitAndRetry(retryTimes,
(exception, timeSpan, retryCount, context) =>
{
LogTo.Warning(
exception,
"WARNING: Unable to save to Raven, will retry after {RetryTimeSpan}, Retry attempt {RetryCount}",
timeSpan,
retryCount);
});
var constant = Backoff.ConstantBackoff(TimeSpan.FromMilliseconds(100), retryCount: 5, fastFirst: true);
var constantPolicy = Policy
.Handle<FooException>()
.WaitAndRetryAsync(constant);
var linear = Backoff.LinearBackoff(TimeSpan.FromMilliseconds(50), retryCount: 5, fastFirst: true);
var linearPolicy = Policy
.Handle<FooException>()
.WaitAndRetryAsync(linear);
var exponential = Backoff.ExponentialBackoff(TimeSpan.FromMilliseconds(20), retryCount: 5, fastFirst: true);
var exponentialPolicy = Policy
.Handle<FooException>()
.WaitAndRetryAsync(exponential);
var jittered = Backoff.DecorrelatedJitterBackoffV2(
medianFirstDelay: TimeSpan.FromMilliseconds(50)
retryCount: 5,
fastFirst: true);
var jitteredPolicy = Policy
.Handle<FooException>()
.WaitAndRetryAsync(jittered);
@HarisMQ
Copy link

HarisMQ commented Jul 29, 2023

Hi,

Should the transientErrors contain the WebExceptionStatus.NameResolutionFailure? I tried the list and upon disconnecting the internet I get this status code of NameResolutionFailure.

Regards,
Haris

@hyrmn
Copy link
Author

hyrmn commented Aug 1, 2023

Hi,

Should the transientErrors contain the WebExceptionStatus.NameResolutionFailure? I tried the list and upon disconnecting the internet I get this status code of NameResolutionFailure.

Regards, Haris

It definitely sounds like it should @HarisMQ. Good catch. The code above only deals with intermittent connectivity issues to upstream services and doesn't account for issues like DNS name resolution. You could add it or add a specific policy for things that may take longer to resolve and then use Policy.Wrap to combine them.

It's also worth exploring the circuit-breaker pattern and the support for that in Polly as you might want to break on something like your internet connection being down so you can provide better messaging back to your users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment