TaskExecution<T>
Represents a single hedging attempt execution alongside all the necessary resources. These are:
Distinct ResilienceContext instance for this execution.
One exception are primary task where the main context is reused.
The cancellation token associated with the execution.
using Polly.Hedging.Utils;
using Polly.Telemetry;
using Polly.Utils;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Polly.Hedging.Controller
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
internal sealed class TaskExecution<[System.Runtime.CompilerServices.Nullable(2)] T>
{
private readonly ResilienceContext _cachedContext = ResilienceContextPool.Shared.Get(default(CancellationToken));
private readonly CancellationTokenSourcePool _cancellationTokenSourcePool;
private readonly TimeProvider _timeProvider;
private readonly ResilienceStrategyTelemetry _telemetry;
private readonly HedgingHandler<T> _handler;
[System.Runtime.CompilerServices.Nullable(2)]
private CancellationTokenSource _cancellationSource;
private CancellationTokenRegistration? _cancellationRegistration;
[System.Runtime.CompilerServices.Nullable(2)]
private ResilienceContext _activeContext;
private long _startExecutionTimestamp;
private long _stopExecutionTimestamp;
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public Task ExecutionTaskSafe {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
[System.Runtime.CompilerServices.NullableContext(2)]
private set;
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
[field: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
public Outcome<T> Outcome {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
get;
[param: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
private set;
}
public bool IsHandled { get; set; }
public bool IsAccepted { get; set; }
public ResilienceProperties Properties { get; } = new ResilienceProperties();
public ResilienceContext Context {
get {
ResilienceContext activeContext = _activeContext;
if (activeContext == null)
throw new InvalidOperationException("TaskExecution is not initialized.");
return activeContext;
}
}
public HedgedTaskType Type { get; set; }
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
[field: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
public Action<TaskExecution<T>> OnReset {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
get;
[param: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1,
1
})]
set;
}
public TimeSpan ExecutionTime => _timeProvider.GetElapsedTime(_startExecutionTimestamp, _stopExecutionTimestamp);
public int AttemptNumber { get; set; }
public TaskExecution(HedgingHandler<T> handler, CancellationTokenSourcePool cancellationTokenSourcePool, TimeProvider timeProvider, ResilienceStrategyTelemetry telemetry)
{
_handler = handler;
_cancellationTokenSourcePool = cancellationTokenSourcePool;
_timeProvider = timeProvider;
_telemetry = telemetry;
}
public void AcceptOutcome()
{
if (ExecutionTaskSafe?.IsCompleted ?? false) {
IsAccepted = true;
return;
}
throw new InvalidOperationException("Unable to accept outcome for a task that is not completed.");
}
public void Cancel()
{
if (!IsAccepted)
_cancellationSource.Cancel();
}
[System.Runtime.CompilerServices.NullableContext(0)]
[AsyncStateMachine(typeof(<InitializeAsync>d__48<>))]
public ValueTask<bool> InitializeAsync<[System.Runtime.CompilerServices.Nullable(2)] TState>(HedgedTaskType type, ContextSnapshot snapshot, [System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
0,
0,
1
})] Func<ResilienceContext, TState, ValueTask<Outcome<T>>> primaryCallback, [System.Runtime.CompilerServices.Nullable(1)] TState state, int attemptNumber)
{
<InitializeAsync>d__48<TState> stateMachine = default(<InitializeAsync>d__48<TState>);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<bool>.Create();
stateMachine.<>4__this = this;
stateMachine.type = type;
stateMachine.snapshot = snapshot;
stateMachine.primaryCallback = primaryCallback;
stateMachine.state = state;
stateMachine.attemptNumber = attemptNumber;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(TaskExecution<>.<HandleOnHedgingAsync>d__49))]
private Task HandleOnHedgingAsync(ResilienceContext primaryContext, int attemptNumber)
{
<HandleOnHedgingAsync>d__49 stateMachine = default(<HandleOnHedgingAsync>d__49);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.primaryContext = primaryContext;
stateMachine.attemptNumber = attemptNumber;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<HandleOnHedgingAsync>d__49>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})]
private HedgingActionGeneratorArguments<TResult> CreateArguments<[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>>> primaryCallback, ResilienceContext primaryContext, TState state, int attempt)
{
return new HedgingActionGeneratorArguments<TResult>(primaryContext, this.Context, attempt, (Func<ResilienceContext, ValueTask<Outcome<TResult>>>)((ResilienceContext context) => primaryCallback(context, state)));
}
[AsyncStateMachine(typeof(TaskExecution<>.<ResetAsync>d__51))]
public ValueTask ResetAsync()
{
<ResetAsync>d__51 stateMachine = default(<ResetAsync>d__51);
stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<ResetAsync>d__51>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(TaskExecution<>.<ExecuteSecondaryActionAsync>d__52))]
private Task ExecuteSecondaryActionAsync([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0,
0,
1
})] Func<ValueTask<Outcome<T>>> action)
{
<ExecuteSecondaryActionAsync>d__52 stateMachine = default(<ExecuteSecondaryActionAsync>d__52);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.action = action;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<ExecuteSecondaryActionAsync>d__52>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(TaskExecution<>.<ExecuteCreateActionException>d__53))]
private Task ExecuteCreateActionException(Exception e)
{
<ExecuteCreateActionException>d__53 stateMachine = default(<ExecuteCreateActionException>d__53);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.e = e;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<ExecuteCreateActionException>d__53>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(<ExecutePrimaryActionAsync>d__54<>))]
private Task ExecutePrimaryActionAsync<[System.Runtime.CompilerServices.Nullable(2)] TState>([System.Runtime.CompilerServices.Nullable(new byte[] {
1,
1,
1,
0,
0,
1
})] Func<ResilienceContext, TState, ValueTask<Outcome<T>>> primaryCallback, TState state)
{
<ExecutePrimaryActionAsync>d__54<TState> stateMachine = default(<ExecutePrimaryActionAsync>d__54<TState>);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.primaryCallback = primaryCallback;
stateMachine.state = state;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<ExecutePrimaryActionAsync>d__54<TState>>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
[AsyncStateMachine(typeof(TaskExecution<>.<UpdateOutcomeAsync>d__55))]
private Task UpdateOutcomeAsync([System.Runtime.CompilerServices.Nullable(new byte[] {
0,
1
})] Outcome<T> outcome)
{
<UpdateOutcomeAsync>d__55 stateMachine = default(<UpdateOutcomeAsync>d__55);
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>4__this = this;
stateMachine.outcome = outcome;
stateMachine.<>1__state = -1;
stateMachine.<>t__builder.Start<<UpdateOutcomeAsync>d__55>(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
private void PrepareContext(ref ContextSnapshot snapshot)
{
if (Type == HedgedTaskType.Primary)
_activeContext = snapshot.Context;
else {
_activeContext = _cachedContext;
_activeContext.InitializeFrom(snapshot.Context);
}
_activeContext.Properties = Properties;
_activeContext.CancellationToken = _cancellationSource.Token;
}
}
}