Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert records to classes #1422

Merged
merged 3 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
martincostello marked this conversation as resolved.
Show resolved Hide resolved
{
}
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