Skip to content

Commit

Permalink
Convert records to classes (#1422)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored Jul 21, 2023
1 parent 7f6b8a4 commit 7199f75
Show file tree
Hide file tree
Showing 42 changed files with 489 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ namespace Polly.CircuitBreaker;
/// <remarks>
/// Always use the constructor when creating this struct, otherwise we do not guarantee binary compatibility.
/// </remarks>
public readonly record struct CircuitBreakerPredicateArguments();
public readonly struct CircuitBreakerPredicateArguments
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected override async ValueTask<Outcome<T>> ExecuteCallbackAsync<TState>(Func

outcome = await ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);

var args = new OutcomeArguments<T, CircuitBreakerPredicateArguments>(context, outcome, new CircuitBreakerPredicateArguments());
var args = new OutcomeArguments<T, CircuitBreakerPredicateArguments>(context, outcome, default);
if (await _handler(args).ConfigureAwait(context.ContinueOnCapturedContext))
{
await _controller.OnActionFailureAsync(outcome, context).ConfigureAwait(context.ContinueOnCapturedContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public ValueTask CloseCircuitAsync(ResilienceContext context)
if (_circuitState == CircuitState.Open && PermitHalfOpenCircuitTest_NeedsLock())
{
_circuitState = CircuitState.HalfOpen;
_telemetry.Report(new(ResilienceEventSeverity.Warning, CircuitBreakerConstants.OnHalfOpenEvent), context, new OnCircuitHalfOpenedArguments());
_telemetry.Report(new(ResilienceEventSeverity.Warning, CircuitBreakerConstants.OnHalfOpenEvent), context, new OnCircuitHalfOpenedArguments(context));
isHalfOpen = true;
}

Expand All @@ -142,7 +142,7 @@ public ValueTask CloseCircuitAsync(ResilienceContext context)

if (isHalfOpen && _onHalfOpen is not null)
{
_executor.ScheduleTask(() => _onHalfOpen(new OnCircuitHalfOpenedArguments()).AsTask(), context, out task);
_executor.ScheduleTask(() => _onHalfOpen(new OnCircuitHalfOpenedArguments(context)).AsTask(), context, out task);
}
}

Expand Down
15 changes: 13 additions & 2 deletions src/Polly.Core/CircuitBreaker/OnCircuitClosedArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,16 @@ namespace Polly.CircuitBreaker;
/// <summary>
/// Arguments used by <see cref="CircuitBreakerStrategyOptions{TResult}.OnClosed"/> event.
/// </summary>
/// <param name="IsManual">Indicates whether the circuit was closed manually by using <see cref="CircuitBreakerManualControl"/>.</param>
public record OnCircuitClosedArguments(bool IsManual);
public sealed class OnCircuitClosedArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="OnCircuitClosedArguments"/> class.
/// </summary>
/// <param name="isManual">Indicates whether the circuit was closed manually by using <see cref="CircuitBreakerManualControl"/>.</param>
public OnCircuitClosedArguments(bool isManual) => IsManual = isManual;

/// <summary>
/// Gets a value indicating whether the circuit was closed manually by using <see cref="CircuitBreakerManualControl"/>.
/// </summary>
public bool IsManual { get; }
}
14 changes: 13 additions & 1 deletion src/Polly.Core/CircuitBreaker/OnCircuitHalfOpenedArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,16 @@ namespace Polly.CircuitBreaker;
/// <summary>
/// Arguments used by <see cref="CircuitBreakerStrategyOptions{TResult}.OnHalfOpened"/> event.
/// </summary>
public record OnCircuitHalfOpenedArguments();
public sealed class OnCircuitHalfOpenedArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="OnCircuitHalfOpenedArguments"/> class.
/// </summary>
/// <param name="context">The context instance.</param>
public OnCircuitHalfOpenedArguments(ResilienceContext context) => Context = context;

/// <summary>
/// Gets the context associated with the execution of a user-provided callback.
/// </summary>
public ResilienceContext Context { get; }
}
26 changes: 23 additions & 3 deletions src/Polly.Core/CircuitBreaker/OnCircuitOpenedArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ namespace Polly.CircuitBreaker;
/// <summary>
/// Arguments used by <see cref="CircuitBreakerStrategyOptions{TResult}.OnOpened"/> event.
/// </summary>
/// <param name="BreakDuration">The duration of break.</param>
/// <param name="IsManual">Indicates whether the circuit was opened manually by using <see cref="CircuitBreakerManualControl"/>.</param>
public record OnCircuitOpenedArguments(TimeSpan BreakDuration, bool IsManual);
public sealed class OnCircuitOpenedArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="OnCircuitOpenedArguments"/> class.
/// </summary>
/// <param name="breakDuration">The duration of break.</param>
/// <param name="isManual">Indicates whether the circuit was opened manually by using <see cref="CircuitBreakerManualControl"/>.</param>
public OnCircuitOpenedArguments(TimeSpan breakDuration, bool isManual)
{
BreakDuration = breakDuration;
IsManual = isManual;
}

/// <summary>
/// Gets the duration of break.
/// </summary>
public TimeSpan BreakDuration { get; }

/// <summary>
/// Gets a value indicating whether the circuit was opened manually by using <see cref="CircuitBreakerManualControl"/>.
/// </summary>
public bool IsManual { get; }
}
4 changes: 3 additions & 1 deletion src/Polly.Core/Fallback/FallbackPredicateArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ namespace Polly.Fallback;
/// <remarks>
/// Always use the constructor when creating this struct, otherwise we do not guarantee binary compatibility.
/// </remarks>
public readonly record struct FallbackPredicateArguments();
public readonly struct FallbackPredicateArguments
{
}
2 changes: 1 addition & 1 deletion src/Polly.Core/Fallback/FallbackResilienceStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public FallbackResilienceStrategy(FallbackHandler<T> handler, Func<OutcomeArgume
protected override async ValueTask<Outcome<T>> ExecuteCallbackAsync<TState>(Func<ResilienceContext, TState, ValueTask<Outcome<T>>> callback, ResilienceContext context, TState state)
{
var outcome = await ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);
var handleFallbackArgs = new OutcomeArguments<T, FallbackPredicateArguments>(context, outcome, new FallbackPredicateArguments());
var handleFallbackArgs = new OutcomeArguments<T, FallbackPredicateArguments>(context, outcome, default);
if (!await _handler.ShouldHandle(handleFallbackArgs).ConfigureAwait(context.ContinueOnCapturedContext))
{
return outcome;
Expand Down
4 changes: 3 additions & 1 deletion src/Polly.Core/Fallback/OnFallbackArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ namespace Polly.Fallback;
/// <summary>
/// Represents arguments used in fallback handling scenarios.
/// </summary>
public record OnFallbackArguments();
public sealed class OnFallbackArguments
{
}
2 changes: 1 addition & 1 deletion src/Polly.Core/Hedging/Controller/TaskExecution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ private async Task ExecutePrimaryActionAsync<TState>(Func<ResilienceContext, TSt

private async Task UpdateOutcomeAsync(Outcome<T> outcome)
{
var args = new OutcomeArguments<T, HedgingPredicateArguments>(Context, outcome, new HedgingPredicateArguments());
var args = new OutcomeArguments<T, HedgingPredicateArguments>(Context, outcome, default);
Outcome = outcome.AsOutcome();
IsHandled = await _handler.ShouldHandle(args).ConfigureAwait(Context.ContinueOnCapturedContext);
TelemetryUtil.ReportExecutionAttempt(_telemetry, Context, outcome, Attempt, ExecutionTime, IsHandled);
Expand Down
59 changes: 48 additions & 11 deletions src/Polly.Core/Hedging/HedgingActionGeneratorArguments.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,57 @@
namespace Polly.Hedging;

#pragma warning disable CA1815 // Override equals and operator equals on value types

/// <summary>
/// Represents arguments used in the hedging resilience strategy.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="PrimaryContext">The primary resilience context.</param>
/// <param name="ActionContext">
/// The context that will be passed to action generated by <see cref="HedgingStrategyOptions{TResult}.HedgingActionGenerator"/>.
/// This context is cloned from <paramref name="PrimaryContext"/>.</param>
/// <param name="Attempt">The zero-based hedging attempt number.</param>
/// <param name="Callback">The callback passed to hedging strategy.</param>
/// <remarks>
/// Always use the constructor when creating this struct, otherwise we do not guarantee binary compatibility.
/// </remarks>
public readonly record struct HedgingActionGeneratorArguments<TResult>(
ResilienceContext PrimaryContext,
ResilienceContext ActionContext,
int Attempt,
Func<ResilienceContext, ValueTask<Outcome<TResult>>> Callback);
public readonly struct HedgingActionGeneratorArguments<TResult>
{
/// <summary>
/// Initializes a new instance of the <see cref="HedgingActionGeneratorArguments{TResult}"/> struct.
/// </summary>
/// <param name="primaryContext">The primary resilience context.</param>
/// <param name="actionContext">
/// The context that will be passed to action generated by <see cref="HedgingStrategyOptions{TResult}.HedgingActionGenerator"/>.
/// .</param>
/// <param name="attempt">The zero-based hedging attempt number.</param>
/// <param name="callback">The callback passed to hedging strategy.</param>
public HedgingActionGeneratorArguments(
ResilienceContext primaryContext,
ResilienceContext actionContext,
int attempt,
Func<ResilienceContext, ValueTask<Outcome<TResult>>> callback)
{
PrimaryContext = primaryContext;
ActionContext = actionContext;
Attempt = attempt;
Callback = callback;
}

/// <summary>
/// Gets the primary resilience context.
/// </summary>
public ResilienceContext PrimaryContext { get; }

/// <summary>
/// Gets the context that will be passed to action generated by <see cref="HedgingStrategyOptions{TResult}.HedgingActionGenerator"/>.
/// </summary>
/// <remarks>
/// This context is cloned from <see cref="PrimaryContext"/>.
/// </remarks>
public ResilienceContext ActionContext { get; }

/// <summary>
/// Gets the zero-based hedging attempt number.
/// </summary>
public int Attempt { get; }

/// <summary>
/// Gets the callback passed to hedging strategy.
/// </summary>
public Func<ResilienceContext, ValueTask<Outcome<TResult>>> Callback { get; }
}
28 changes: 25 additions & 3 deletions src/Polly.Core/Hedging/HedgingDelayArguments.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,33 @@
namespace Polly.Hedging;

#pragma warning disable CA1815 // Override equals and operator equals on value types

/// <summary>
/// Arguments used by hedging delay generator.
/// </summary>
/// <param name="Context">The context associated with the execution of a user-provided callback.</param>
/// <param name="Attempt">The zero-based hedging attempt number.</param>
/// <remarks>
/// Always use the constructor when creating this struct, otherwise we do not guarantee binary compatibility.
/// </remarks>
public readonly record struct HedgingDelayArguments(ResilienceContext Context, int Attempt);
public readonly struct HedgingDelayArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="HedgingDelayArguments"/> struct.
/// </summary>
/// <param name="context">The context associated with the execution of a user-provided callback.</param>
/// <param name="attempt">The zero-based hedging attempt number.</param>
public HedgingDelayArguments(ResilienceContext context, int attempt)
{
Context = context;
Attempt = attempt;
}

/// <summary>
/// Gets the context associated with the execution of a user-provided callback.
/// </summary>
public ResilienceContext Context { get; }

/// <summary>
/// Gets the zero-based hedging attempt number.
/// </summary>
public int Attempt { get; }
}
4 changes: 3 additions & 1 deletion src/Polly.Core/Hedging/HedgingPredicateArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ namespace Polly.Hedging;
/// <remarks>
/// Always use the constructor when creating this struct, otherwise we do not guarantee binary compatibility.
/// </remarks>
public readonly record struct HedgingPredicateArguments();
public readonly struct HedgingPredicateArguments
{
}
4 changes: 2 additions & 2 deletions src/Polly.Core/Hedging/HedgingResilienceStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ private async ValueTask<Outcome<T>> ExecuteCoreAsync<TState>(
await HandleOnHedgingAsync(
context,
Outcome.FromResult<T>(default),
new OnHedgingArguments(attempt, HasOutcome: false, ExecutionTime: delay)).ConfigureAwait(context.ContinueOnCapturedContext);
new OnHedgingArguments(attempt, hasOutcome: false, executionTime: delay)).ConfigureAwait(context.ContinueOnCapturedContext);
continue;
}

Expand All @@ -115,7 +115,7 @@ await HandleOnHedgingAsync(
await HandleOnHedgingAsync(
context,
outcome,
new OnHedgingArguments(attempt, HasOutcome: true, executionTime)).ConfigureAwait(context.ContinueOnCapturedContext);
new OnHedgingArguments(attempt, hasOutcome: true, executionTime)).ConfigureAwait(context.ContinueOnCapturedContext);
}
}

Expand Down
43 changes: 33 additions & 10 deletions src/Polly.Core/Hedging/OnHedgingArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,36 @@ namespace Polly.Hedging;
/// <summary>
/// Represents arguments used by the on-hedging event.
/// </summary>
/// <param name="Attempt">The zero-based hedging attempt number.</param>
/// <param name="HasOutcome">
/// Determines whether the outcome is available before loading the next hedged task.
/// No outcome indicates that the previous action did not finish within the hedging delay.
/// </param>
/// <param name="ExecutionTime">
/// The execution time of hedging attempt or the hedging delay
/// in case the attempt was not finished in time.
/// </param>
public record OnHedgingArguments(int Attempt, bool HasOutcome, TimeSpan ExecutionTime);
public sealed class OnHedgingArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="OnHedgingArguments"/> class.
/// </summary>
/// <param name="attempt">The zero-based hedging attempt number.</param>
/// <param name="hasOutcome">Indicates whether outcome is available.</param>
/// <param name="executionTime">The execution time of hedging attempt or the hedging delay in case the attempt was not finished in time.</param>
public OnHedgingArguments(int attempt, bool hasOutcome, TimeSpan executionTime)
{
Attempt = attempt;
HasOutcome = hasOutcome;
ExecutionTime = executionTime;
}

/// <summary>
/// Gets the zero-based hedging attempt number.
/// </summary>
public int Attempt { get; }

/// <summary>
/// Gets a value indicating whether the outcome is available before loading the next hedged task.
/// </summary>
/// <remarks>
/// No outcome indicates that the previous action did not finish within the hedging delay.
/// </remarks>
public bool HasOutcome { get; }

/// <summary>
/// Gets the execution time of hedging attempt or the hedging delay in case the attempt was not finished in time.
/// </summary>
public TimeSpan ExecutionTime { get; }
}
Loading

0 comments on commit 7199f75

Please sign in to comment.