ClientRetryPolicy
using Microsoft.Extensions.Logging;
using System.ClientModel.Internal;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace System.ClientModel.Primitives
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class ClientRetryPolicy : PipelinePolicy
{
private static readonly TimeSpan DefaultInitialDelay = TimeSpan.FromSeconds(0.8);
private readonly int _maxRetries;
private readonly TimeSpan _initialDelay;
[System.Runtime.CompilerServices.Nullable(2)]
private readonly PipelineRetryLogger _retryLogger;
internal const int DefaultMaxRetries = 3;
public static ClientRetryPolicy Default { get; } = new ClientRetryPolicy(3);
public ClientRetryPolicy(int maxRetries = 3)
: this(maxRetries, true, null)
{
}
[System.Runtime.CompilerServices.NullableContext(2)]
public ClientRetryPolicy(int maxRetries, bool enableLogging, ILoggerFactory loggerFactory)
{
_maxRetries = maxRetries;
_initialDelay = DefaultInitialDelay;
_retryLogger = (enableLogging ? new PipelineRetryLogger(loggerFactory) : null);
}
public sealed override void Process(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int currentIndex)
{
ProcessSyncOrAsync(message, pipeline, currentIndex, false).EnsureCompleted();
}
[AsyncStateMachine(typeof(<ProcessAsync>d__11))]
public sealed override ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int currentIndex)
{
<ProcessAsync>d__11 stateMachine = default(<ProcessAsync>d__11);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.message = message;
stateMachine.pipeline = pipeline;
stateMachine.currentIndex = currentIndex;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ProcessSyncOrAsync>d__12))]
private ValueTask ProcessSyncOrAsync(PipelineMessage message, IReadOnlyList<PipelinePolicy> pipeline, int currentIndex, bool async)
{
<ProcessSyncOrAsync>d__12 stateMachine = default(<ProcessSyncOrAsync>d__12);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.message = message;
stateMachine.pipeline = pipeline;
stateMachine.currentIndex = currentIndex;
stateMachine.async = async;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
protected virtual void OnSendingRequest(PipelineMessage message)
{
}
protected virtual ValueTask OnSendingRequestAsync(PipelineMessage message)
{
return default(ValueTask);
}
protected virtual void OnRequestSent(PipelineMessage message)
{
}
protected virtual ValueTask OnRequestSentAsync(PipelineMessage message)
{
return default(ValueTask);
}
protected virtual void OnTryComplete(PipelineMessage message)
{
}
internal bool ShouldRetryInternal(PipelineMessage message, [System.Runtime.CompilerServices.Nullable(2)] Exception exception)
{
return ShouldRetryInternalSyncOrAsync(message, exception, false).EnsureCompleted();
}
[System.Runtime.CompilerServices.NullableContext(0)]
[AsyncStateMachine(typeof(<ShouldRetryInternalAsync>d__19))]
internal ValueTask<bool> ShouldRetryInternalAsync([System.Runtime.CompilerServices.Nullable(1)] PipelineMessage message, [System.Runtime.CompilerServices.Nullable(2)] Exception exception)
{
<ShouldRetryInternalAsync>d__19 stateMachine = default(<ShouldRetryInternalAsync>d__19);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<bool>.Create();
stateMachine.<>4__this = this;
stateMachine.message = message;
stateMachine.exception = exception;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[System.Runtime.CompilerServices.NullableContext(0)]
[AsyncStateMachine(typeof(<ShouldRetryInternalSyncOrAsync>d__20))]
private ValueTask<bool> ShouldRetryInternalSyncOrAsync([System.Runtime.CompilerServices.Nullable(1)] PipelineMessage message, [System.Runtime.CompilerServices.Nullable(2)] Exception exception, bool async)
{
<ShouldRetryInternalSyncOrAsync>d__20 stateMachine = default(<ShouldRetryInternalSyncOrAsync>d__20);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<bool>.Create();
stateMachine.<>4__this = this;
stateMachine.message = message;
stateMachine.exception = exception;
stateMachine.async = async;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
protected virtual bool ShouldRetry(PipelineMessage message, [System.Runtime.CompilerServices.Nullable(2)] Exception exception)
{
if (message.RetryCount >= _maxRetries)
return false;
if (!message.ResponseClassifier.TryClassify(message, exception, out bool isRetriable))
PipelineMessageClassifier.Default.TryClassify(message, exception, out isRetriable);
return isRetriable;
}
[System.Runtime.CompilerServices.NullableContext(0)]
protected virtual ValueTask<bool> ShouldRetryAsync([System.Runtime.CompilerServices.Nullable(1)] PipelineMessage message, [System.Runtime.CompilerServices.Nullable(2)] Exception exception)
{
return new ValueTask<bool>(ShouldRetry(message, exception));
}
protected virtual TimeSpan GetNextDelay(PipelineMessage message, int tryCount)
{
double num = (double)(1 << tryCount - 1) * _initialDelay.TotalMilliseconds;
TimeSpan value;
if (message.Response != null && PipelineResponseHeaders.TryGetRetryAfter(message.Response, out value) && value.TotalMilliseconds > num)
return value;
return TimeSpan.FromMilliseconds(num);
}
[AsyncStateMachine(typeof(<WaitAsync>d__24))]
protected virtual Task WaitAsync(TimeSpan time, CancellationToken cancellationToken)
{
<WaitAsync>d__24 stateMachine = default(<WaitAsync>d__24);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.time = time;
stateMachine.cancellationToken = cancellationToken;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
protected virtual void Wait(TimeSpan time, CancellationToken cancellationToken)
{
if (cancellationToken.WaitHandle.WaitOne(time))
CancellationHelper.ThrowIfCancellationRequested(cancellationToken, null);
}
}
}