ResilienceStrategyPipeline
A pipeline of strategies.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace Polly.Utils
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
[DebuggerDisplay("ResilienceStrategyPipeline, Strategies = {Strategies.Count}")]
[DebuggerTypeProxy(typeof(DebuggerProxy))]
internal sealed class ResilienceStrategyPipeline : ResilienceStrategy
{
[System.Runtime.CompilerServices.NullableContext(2)]
[System.Runtime.CompilerServices.Nullable(0)]
private sealed class DelegatingResilienceStrategy : ResilienceStrategy
{
[System.Runtime.CompilerServices.Nullable(1)]
private readonly ResilienceStrategy _strategy;
public ResilienceStrategy Next { get; set; }
[System.Runtime.CompilerServices.NullableContext(1)]
public DelegatingResilienceStrategy(ResilienceStrategy strategy)
{
_strategy = strategy;
}
[System.Runtime.CompilerServices.NullableContext(1)]
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
0,
1
})]
protected internal override ValueTask<Outcome<TResult>> ExecuteCore<[System.Runtime.CompilerServices.Nullable(2)] TResult, [System.Runtime.CompilerServices.Nullable(2)] TState>([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
0,
0,
1
})] Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback, ResilienceContext context, TState state)
{
return _strategy.ExecuteCore(delegate(ResilienceContext context, (ResilienceStrategy Next, Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback, TState state) state) {
if (context.CancellationToken.IsCancellationRequested)
return Outcome.FromExceptionAsTask<TResult>((Exception)ExceptionUtilities.TrySetStackTrace<OperationCanceledException>(new OperationCanceledException(context.CancellationToken)));
return state.Next.ExecuteCore<TResult, TState>(state.callback, context, state.state);
}, context, (Next, callback, state));
}
}
[System.Runtime.CompilerServices.Nullable(0)]
internal sealed class DebuggerProxy
{
private readonly ResilienceStrategyPipeline _resilienceStrategy;
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public IEnumerable<ResilienceStrategy> Strategies {
get {
return _resilienceStrategy.Strategies;
}
}
public DebuggerProxy(ResilienceStrategyPipeline resilienceStrategy)
{
_resilienceStrategy = resilienceStrategy;
}
}
private readonly ResilienceStrategy _pipeline;
public IReadOnlyList<ResilienceStrategy> Strategies { get; }
public static ResilienceStrategyPipeline CreatePipeline(IReadOnlyList<ResilienceStrategy> strategies)
{
Guard.NotNull(strategies, "strategies");
if (strategies.Count < 2)
throw new InvalidOperationException("The resilience pipeline must contain at least two resilience strategies.");
if (strategies.Distinct().Count() != strategies.Count)
throw new InvalidOperationException("The resilience pipeline must contain unique resilience strategies.");
List<DelegatingResilienceStrategy> list = (from strategy in strategies.Take(strategies.Count - 1)
select new DelegatingResilienceStrategy(strategy)).ToList();
List<DelegatingResilienceStrategy> list2 = list;
list2[list2.Count - 1].Next = strategies[strategies.Count - 1];
for (int i = 0; i < list.Count - 1; i++) {
list[i].Next = list[i + 1];
}
return new ResilienceStrategyPipeline(list[0], strategies);
}
private ResilienceStrategyPipeline(ResilienceStrategy pipeline, IReadOnlyList<ResilienceStrategy> strategies)
{
Strategies = strategies;
_pipeline = pipeline;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
0,
1
})]
protected internal override ValueTask<Outcome<TResult>> ExecuteCore<[System.Runtime.CompilerServices.Nullable(2)] TResult, [System.Runtime.CompilerServices.Nullable(2)] TState>([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
0,
0,
1
})] Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback, ResilienceContext context, TState state)
{
if (context.CancellationToken.IsCancellationRequested)
return Outcome.FromExceptionAsTask<TResult>(new OperationCanceledException(context.CancellationToken).TrySetStackTrace());
return _pipeline.ExecuteCore(callback, context, state);
}
}
}