Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk committed May 14, 2023
1 parent 39548d7 commit de54a62
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 31 deletions.
15 changes: 13 additions & 2 deletions src/Polly.Core.Tests/Retry/RetryHelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Linq;
using Polly.Contrib.WaitAndRetry;
using Polly.Retry;
using Polly.Utils;
Expand Down Expand Up @@ -90,14 +91,24 @@ public void ExponentialWithJitter_Ok(int count)
newDelays.Should().HaveCount(oldDelays.Count);
}

private static IReadOnlyList<TimeSpan> GetExponentialWithJitterBackoff(bool contrib, TimeSpan baseDelay, int retryCount)
[Fact]
public void ExponentialWithJitter_EnsureRandomness()
{
var delay = TimeSpan.FromSeconds(7.8);
var delays1 = GetExponentialWithJitterBackoff(false, delay, 100, RandomUtil.Instance);
var delays2 = GetExponentialWithJitterBackoff(false, delay, 100, RandomUtil.Instance);

delays1.SequenceEqual(delays2).Should().BeFalse();
}

private static IReadOnlyList<TimeSpan> GetExponentialWithJitterBackoff(bool contrib, TimeSpan baseDelay, int retryCount, RandomUtil? util = null)
{
if (contrib)
{
return Backoff.DecorrelatedJitterBackoffV2(baseDelay, retryCount, 0, false).Take(retryCount).ToArray();
}

var random = new RandomUtil(0);
var random = util ?? new RandomUtil(0);
double state = 0;
var result = new List<TimeSpan>();

Expand Down
26 changes: 13 additions & 13 deletions src/Polly.Core/Retry/RetryBackoffType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ namespace Polly.Retry;
/// </summary>
public enum RetryBackoffType
{
/// <summary>
/// Exponential delay with randomization retry type,
/// making sure to mitigate any correlations.
/// </summary>
/// <example>
/// 850ms, 1455ms, 3060ms.
/// </example>
/// <remarks>
/// In transient failures handling scenarios, this is the
/// <see href=" https://github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry#new-jitter-recommendation"> recommended retry type</see>.
/// </remarks>
ExponentialWithJitter,

/// <summary>
/// The constant retry type.
/// </summary>
Expand Down Expand Up @@ -38,17 +51,4 @@ public enum RetryBackoffType
/// 200ms, 400ms, 800ms.
/// </example>
Exponential,

/// <summary>
/// Exponential delay with randomization retry type,
/// making sure to mitigate any correlations.
/// </summary>
/// <example>
/// 850ms, 1455ms, 3060ms.
/// </example>
/// <remarks>
/// In transient failures handling scenarios, this is the
/// <see href=" https://github.com/Polly-Contrib/Polly.Contrib.WaitAndRetry#new-jitter-recommendation"> recommended retry type</see>.
/// </remarks>
ExponentialWithJitter,
}
12 changes: 6 additions & 6 deletions src/Polly.Core/Retry/RetryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ public static TimeSpan GetRetryDelay(RetryBackoffType type, int attempt, TimeSpa
/// <summary>
/// Generates sleep durations in an exponentially backing-off, jittered manner, making sure to mitigate any correlations.
/// For example: 850ms, 1455ms, 3060ms.
/// Per discussion in Polly issue 530, the jitter of this implementation exhibits fewer spikes and a smoother distribution than the AWS jitter formula.
/// Per discussion in Polly issue https://github.com/App-vNext/Polly/issues/530, the jitter of this implementation exhibits fewer spikes and a smoother distribution than the AWS jitter formula.
/// </summary>
/// <param name="attempt">The current attempt.</param>
/// <param name="baseDelay">The median delay to target before the first retry, call it f (= f * 2^0).
/// <param name="baseDelay">The median delay to target before the first retry, call it <c>f (= f * 2^0).</c>
/// Choose this value both to approximate the first delay, and to scale the remainder of the series.
/// Subsequent retries will (over a large sample size) have a median approximating retries at time f * 2^1, f * 2^2 ... f * 2^t etc for try t.
/// The actual amount of delay-before-retry for try t may be distributed between 0 and f * (2^(t+1) - 2^(t-1)) for t >= 2;
/// or between 0 and f * 2^(t+1), for t is 0 or 1.</param>
/// Subsequent retries will (over a large sample size) have a median approximating retries at time <c>f * 2^1, f * 2^2 ... f * 2^t</c> etc for try t.
/// The actual amount of delay-before-retry for try t may be distributed between 0 and <c>f * (2^(t+1) - 2^(t-1)) for t >= 2;</c>
/// or between 0 and <c>f * 2^(t+1)</c>, for t is 0 or 1.</param>
/// <param name="prev">The previous state value used for calculations.</param>
/// <param name="random">The random utility to use.</param>
/// <remarks>
Expand All @@ -50,7 +50,7 @@ private static TimeSpan DecorrelatedJitterBackoffV2(int attempt, TimeSpan baseDe
{
// The original author/credit for this jitter formula is @george-polevoy .
// Jitter formula used with permission as described at https://github.com/App-vNext/Polly/issues/530#issuecomment-526555979
// Minor adaptations (pFactor = 4.0 and rpScalingFactor = 1 / 1.4d) by @reisenberger, to scale the formula output for easier parameterisation to users.
// Minor adaptations (pFactor = 4.0 and rpScalingFactor = 1 / 1.4d) by @reisenberger, to scale the formula output for easier parameterization to users.

// A factor used within the formula to help smooth the first calculated delay.
const double PFactor = 4.0;
Expand Down
24 changes: 19 additions & 5 deletions src/Polly.Core/Retry/RetryStrategyOptions.TResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,32 @@ public class RetryStrategyOptions<TResult> : ResilienceStrategyOptions
/// Gets or sets the type of the back-off.
/// </summary>
/// <remarks>
/// Defaults to <see cref="RetryBackoffType.Exponential"/>.
/// Defaults to <see cref="RetryBackoffType.ExponentialWithJitter"/>.
/// </remarks>
public RetryBackoffType BackoffType { get; set; } = RetryConstants.DefaultBackoffType;

/// <summary>
/// Gets or sets the delay between retries based on the backoff type, <see cref="RetryBackoffType"/>.
/// Gets or sets the base delay between retries.
/// </summary>
/// <remarks>
/// This value is used with the combination of <see cref="BackoffType"/> to generate the final delay for each individual retry attempt:
/// <list type="bullet">
/// <item>
/// <see cref="RetryBackoffType.Exponential"/>: Represents the median delay to target before the first retry.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.ExponentialWithJitter"/>: Represents the median delay to target before the first retry.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.Linear"/>: Represents the initial delay, the following delays increasing linearly with this value.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.Constant"/> Represents the constant delay between retries.
/// </item>
/// </list>
/// <para>
/// Defaults to 2 seconds.
/// For <see cref="RetryBackoffType.Exponential"/> this represents the median delay to target before the first retry.
/// For the <see cref="RetryBackoffType.Linear"/> it represents the initial delay, the following delays increasing linearly with this value.
/// In case of <see cref="RetryBackoffType.Constant"/> it represents the constant delay between retries.
/// </para>
/// </remarks>
[TimeSpan("00:00:00", "1.00:00:00")]
public TimeSpan BaseDelay { get; set; } = RetryConstants.DefaultBaseDelay;
Expand Down
24 changes: 19 additions & 5 deletions src/Polly.Core/Retry/RetryStrategyOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,32 @@ public class RetryStrategyOptions : ResilienceStrategyOptions
/// Gets or sets the type of the back-off.
/// </summary>
/// <remarks>
/// Defaults to <see cref="RetryBackoffType.Exponential"/>.
/// Defaults to <see cref="RetryBackoffType.ExponentialWithJitter"/>.
/// </remarks>
public RetryBackoffType BackoffType { get; set; } = RetryConstants.DefaultBackoffType;

/// <summary>
/// Gets or sets the delay between retries based on the backoff type, <see cref="RetryBackoffType"/>.
/// Gets or sets the base delay between retries.
/// </summary>
/// <remarks>
/// This value is used with the combination of <see cref="BackoffType"/> to generate the final delay for each individual retry attempt:
/// <list type="bullet">
/// <item>
/// <see cref="RetryBackoffType.Exponential"/>: Represents the median delay to target before the first retry.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.ExponentialWithJitter"/>: Represents the median delay to target before the first retry.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.Linear"/>: Represents the initial delay, the following delays increasing linearly with this value.
/// </item>
/// <item>
/// <see cref="RetryBackoffType.Constant"/> Represents the constant delay between retries.
/// </item>
/// </list>
/// <para>
/// Defaults to 2 seconds.
/// For <see cref="RetryBackoffType.Exponential"/> this represents the median delay to target before the first retry.
/// For the <see cref="RetryBackoffType.Linear"/> it represents the initial delay, the following delays increasing linearly with this value.
/// In case of <see cref="RetryBackoffType.Constant"/> it represents the constant delay between retries.
/// </para>
/// </remarks>
[TimeSpan("00:00:00", "1.00:00:00")]
public TimeSpan BaseDelay { get; set; } = RetryConstants.DefaultBaseDelay;
Expand Down

0 comments on commit de54a62

Please sign in to comment.