<PackageReference Include="Polly.Core" Version="8.1.0" />

HedgingExecutionContext<T>

The context associated with an execution of hedging resilience strategy. It holds the resources for all executed hedged tasks (primary + secondary) and is responsible for resource disposal.
using Polly.Hedging.Controller; using Polly.Utils; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace Polly.Hedging.Utils { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal sealed class HedgingExecutionContext<[System.Runtime.CompilerServices.Nullable(2)] T> : IAsyncDisposable { [System.Runtime.CompilerServices.NullableContext(0)] public readonly struct ExecutionInfo<[System.Runtime.CompilerServices.Nullable(2)] TResult> : IEquatable<ExecutionInfo<TResult>> { [System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] [field: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] public TaskExecution<T> Execution { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] get; [param: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] set; } public bool Loaded { get; set; } [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] [field: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] public Outcome<TResult>? Outcome { [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] get; [param: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] set; } public ExecutionInfo([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] TaskExecution<T> Execution, bool Loaded, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] Outcome<TResult>? Outcome) { Execution = Execution; Loaded = Loaded; Outcome = Outcome; } [CompilerGenerated] public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("ExecutionInfo"); stringBuilder.Append(" { "); if (PrintMembers(stringBuilder)) stringBuilder.Append(' '); stringBuilder.Append('}'); return stringBuilder.ToString(); } [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { builder.Append("Execution = "); builder.Append(Execution); builder.Append(", Loaded = "); builder.Append(Loaded.ToString()); builder.Append(", Outcome = "); builder.Append(Outcome.ToString()); return true; } public static bool operator !=(ExecutionInfo<TResult> left, ExecutionInfo<TResult> right) { return !(left == right); } public static bool operator ==(ExecutionInfo<TResult> left, ExecutionInfo<TResult> right) { return left.Equals(right); } [CompilerGenerated] public override int GetHashCode() { return (EqualityComparer<TaskExecution<T>>.Default.GetHashCode(Execution) * -1521134295 + EqualityComparer<bool>.Default.GetHashCode(Loaded)) * -1521134295 + EqualityComparer<Outcome<TResult>?>.Default.GetHashCode(Outcome); } [CompilerGenerated] public override bool Equals(object obj) { if (obj is ExecutionInfo<TResult>) return Equals((ExecutionInfo<TResult>)obj); return false; } [CompilerGenerated] public bool Equals(ExecutionInfo<TResult> other) { if (EqualityComparer<TaskExecution<T>>.Default.Equals(Execution, other.Execution) && EqualityComparer<bool>.Default.Equals(Loaded, other.Loaded)) return EqualityComparer<Outcome<TResult>?>.Default.Equals(Outcome, other.Outcome); return false; } [CompilerGenerated] public void Deconstruct([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] out TaskExecution<T> Execution, out bool Loaded, [System.Runtime.CompilerServices.Nullable(new byte[] { 0, 1 })] out Outcome<TResult>? Outcome) { Execution = this.Execution; Loaded = this.Loaded; Outcome = this.Outcome; } } private readonly List<TaskExecution<T>> _tasks = new List<TaskExecution<T>>(); private readonly List<TaskExecution<T>> _executingTasks = new List<TaskExecution<T>>(); private readonly ObjectPool<TaskExecution<T>> _executionPool; private readonly TimeProvider _timeProvider; private readonly int _maxAttempts; private readonly Action<HedgingExecutionContext<T>> _onReset; public int LoadedTasks => _tasks.Count; [System.Runtime.CompilerServices.Nullable(2)] [field: System.Runtime.CompilerServices.Nullable(2)] public ResilienceContext PrimaryContext { [System.Runtime.CompilerServices.NullableContext(2)] get; [System.Runtime.CompilerServices.NullableContext(2)] private set; } public bool IsInitialized => PrimaryContext != null; public IReadOnlyList<TaskExecution<T>> Tasks => _tasks; private bool ContinueOnCapturedContext => PrimaryContext.ContinueOnCapturedContext; public HedgingExecutionContext(ObjectPool<TaskExecution<T>> executionPool, TimeProvider timeProvider, int maxAttempts, Action<HedgingExecutionContext<T>> onReset) { _executionPool = executionPool; _timeProvider = timeProvider; _maxAttempts = maxAttempts; _onReset = onReset; } internal void Initialize(ResilienceContext context) { PrimaryContext = context; } [AsyncStateMachine(typeof(<LoadExecutionAsync>d__21<>))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 0, 0, 1 })] public ValueTask<ExecutionInfo<T>> LoadExecutionAsync<[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) { <LoadExecutionAsync>d__21<TState> stateMachine = default(<LoadExecutionAsync>d__21<TState>); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<ExecutionInfo<T>>.Create(); stateMachine.<>4__this = this; stateMachine.primaryCallback = primaryCallback; stateMachine.state = state; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(HedgingExecutionContext<>.<DisposeAsync>d__22))] public ValueTask DisposeAsync() { <DisposeAsync>d__22 stateMachine = default(<DisposeAsync>d__22); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start<<DisposeAsync>d__22>(ref stateMachine); return stateMachine.<>t__builder.Task; } [AsyncStateMachine(typeof(HedgingExecutionContext<>.<TryWaitForCompletedExecutionAsync>d__23))] [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 2, 1 })] public ValueTask<TaskExecution<T>> TryWaitForCompletedExecutionAsync(TimeSpan hedgingDelay) { <TryWaitForCompletedExecutionAsync>d__23 stateMachine = default(<TryWaitForCompletedExecutionAsync>d__23); stateMachine.<>t__builder = AsyncValueTaskMethodBuilder<TaskExecution<T>>.Create(); stateMachine.<>4__this = this; stateMachine.hedgingDelay = hedgingDelay; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 0, 0, 1 })] private ExecutionInfo<T> CreateExecutionInfoWhenNoExecution() { if (_executingTasks.Count == 0) { TaskExecution<T> taskExecution = Enumerable.First<TaskExecution<T>>((IEnumerable<TaskExecution<T>>)_tasks, (Func<TaskExecution<T>, bool>)((TaskExecution<T> t) => t.ExecutionTaskSafe.IsCompleted)); taskExecution.AcceptOutcome(); return new ExecutionInfo<T>(null, false, taskExecution.Outcome); } return new ExecutionInfo<T>(null, false, null); } private Task<Task> WaitForTaskCompetitionAsync() { switch (_executingTasks.Count) { case 1: return <WaitForTaskCompetitionAsync>g__AwaitTask|25_0(_executingTasks[0], ContinueOnCapturedContext); case 2: return Task.WhenAny(new Task[2] { _executingTasks[0].ExecutionTaskSafe, _executingTasks[1].ExecutionTaskSafe }); default: return Task.WhenAny(Enumerable.Select<TaskExecution<T>, Task>((IEnumerable<TaskExecution<T>>)_executingTasks, (Func<TaskExecution<T>, Task>)((TaskExecution<T> v) => v.ExecutionTaskSafe))); } } [return: System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] private TaskExecution<T> TryRemoveExecutedTask() { TaskExecution<T> taskExecution = _executingTasks.Find((TaskExecution<T> v) => v.ExecutionTaskSafe.IsCompleted); if (taskExecution != null) { _executingTasks.Remove(taskExecution); return taskExecution; } return null; } private void UpdateOriginalContext() { if (LoadedTasks != 0) { TaskExecution<T> taskExecution = Enumerable.FirstOrDefault<TaskExecution<T>>((IEnumerable<TaskExecution<T>>)Tasks, (Func<TaskExecution<T>, bool>)((TaskExecution<T> t) => t.IsAccepted)); if (taskExecution != null) PrimaryContext.Properties.AddOrReplaceProperties(taskExecution.Context.Properties); } } private void Reset() { _tasks.Clear(); _executingTasks.Clear(); PrimaryContext = null; _onReset(this); } } }