diff --git a/src/Polly.Core/CircuitBreaker/BreakDurationGeneratorArguments.cs b/src/Polly.Core/CircuitBreaker/BreakDurationGeneratorArguments.cs
index 8883f6dd774..a16f8547539 100644
--- a/src/Polly.Core/CircuitBreaker/BreakDurationGeneratorArguments.cs
+++ b/src/Polly.Core/CircuitBreaker/BreakDurationGeneratorArguments.cs
@@ -7,10 +7,11 @@ namespace Polly.CircuitBreaker;
///
/// Represents arguments used to generate a dynamic break duration for a circuit breaker.
///
-public readonly struct BreakDurationGeneratorArguments
+/// The type of result.
+public readonly struct BreakDurationGeneratorArguments
{
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The failure rate at which the circuit breaker should trip.
/// It represents the ratio of failed actions to the total executed actions.
@@ -18,20 +19,19 @@ public readonly struct BreakDurationGeneratorArguments
/// This count is used to determine if the failure threshold has been reached.
/// The resilience context providing additional information
/// about the execution state and failures.
+ /// The outcome of the resilience operation or event.
[EditorBrowsable(EditorBrowsableState.Never)]
public BreakDurationGeneratorArguments(
double failureRate,
int failureCount,
- ResilienceContext context)
+ ResilienceContext context,
+ Outcome outcome)
+ : this(failureRate, failureCount, context, 0, outcome)
{
- FailureRate = failureRate;
- FailureCount = failureCount;
- Context = context;
- HalfOpenAttempts = 0;
}
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The failure rate at which the circuit breaker should trip.
/// It represents the ratio of failed actions to the total executed actions.
@@ -40,16 +40,19 @@ public BreakDurationGeneratorArguments(
/// The resilience context providing additional information
/// about the execution state and failures.
/// The number of half-open attempts.
+ /// The outcome of the resilience operation or event.
public BreakDurationGeneratorArguments(
double failureRate,
int failureCount,
ResilienceContext context,
- int halfOpenAttempts)
+ int halfOpenAttempts,
+ Outcome outcome)
{
FailureRate = failureRate;
FailureCount = failureCount;
Context = context;
HalfOpenAttempts = halfOpenAttempts;
+ Outcome = outcome;
}
///
@@ -71,4 +74,9 @@ public BreakDurationGeneratorArguments(
/// Gets the number of half-open attempts.
///
public int HalfOpenAttempts { get; }
+
+ ///
+ /// Gets the outcome of the user-specified callback.
+ ///
+ public Outcome Outcome { get; }
}
diff --git a/src/Polly.Core/CircuitBreaker/CircuitBreakerStrategyOptions.TResult.cs b/src/Polly.Core/CircuitBreaker/CircuitBreakerStrategyOptions.TResult.cs
index 8d1bdbdeec1..d867158a4ea 100644
--- a/src/Polly.Core/CircuitBreaker/CircuitBreakerStrategyOptions.TResult.cs
+++ b/src/Polly.Core/CircuitBreaker/CircuitBreakerStrategyOptions.TResult.cs
@@ -75,7 +75,7 @@ public class CircuitBreakerStrategyOptions : ResilienceStrategyOptions
///
/// The default value is .
///
- public Func>? BreakDurationGenerator { get; set; }
+ public Func, ValueTask>? BreakDurationGenerator { get; set; }
///
/// Gets or sets a predicate that determines whether the outcome should be handled by the circuit breaker.
diff --git a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs
index 40dd2c5e35a..8cfcfc9573c 100644
--- a/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs
+++ b/src/Polly.Core/CircuitBreaker/Controller/CircuitStateController.cs
@@ -16,7 +16,7 @@ internal sealed class CircuitStateController : IDisposable
private readonly ResilienceStrategyTelemetry _telemetry;
private readonly CircuitBehavior _behavior;
private readonly TimeSpan _breakDuration;
- private readonly Func>? _breakDurationGenerator;
+ private readonly Func, ValueTask>? _breakDurationGenerator;
private DateTimeOffset _blockedUntil;
private CircuitState _circuitState = CircuitState.Closed;
private Outcome? _lastOutcome;
@@ -33,7 +33,7 @@ public CircuitStateController(
CircuitBehavior behavior,
TimeProvider timeProvider,
ResilienceStrategyTelemetry telemetry,
- Func>? breakDurationGenerator)
+ Func, ValueTask>? breakDurationGenerator)
#pragma warning restore S107
{
_breakDuration = breakDuration;
@@ -323,7 +323,7 @@ private void OpenCircuitFor_NeedsLock(Outcome outcome, TimeSpan breakDuration
{
#pragma warning disable CA2012
#pragma warning disable S1226
- breakDuration = _breakDurationGenerator(new(_behavior.FailureRate, _behavior.FailureCount, context, _halfOpenAttempts)).GetAwaiter().GetResult();
+ breakDuration = _breakDurationGenerator(new(_behavior.FailureRate, _behavior.FailureCount, context, _halfOpenAttempts, outcome)).GetAwaiter().GetResult();
#pragma warning restore S1226
#pragma warning restore CA2012
}
diff --git a/src/Polly.Core/PublicAPI.Shipped.txt b/src/Polly.Core/PublicAPI.Shipped.txt
index 0815ba16d14..aba24b30999 100644
--- a/src/Polly.Core/PublicAPI.Shipped.txt
+++ b/src/Polly.Core/PublicAPI.Shipped.txt
@@ -11,14 +11,15 @@ override Polly.Registry.ResiliencePipelineRegistry.TryGetPipeline(TKey key
override Polly.Registry.ResiliencePipelineRegistry.TryGetPipeline(TKey key, out Polly.ResiliencePipeline? pipeline) -> bool
override Polly.ResiliencePropertyKey.ToString() -> string!
override Polly.Telemetry.ResilienceEvent.ToString() -> string!
-Polly.CircuitBreaker.BreakDurationGeneratorArguments
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments() -> void
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments(double failureRate, int failureCount, Polly.ResilienceContext! context) -> void
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments(double failureRate, int failureCount, Polly.ResilienceContext! context, int halfOpenAttempts) -> void
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.Context.get -> Polly.ResilienceContext!
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureCount.get -> int
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureRate.get -> double
-Polly.CircuitBreaker.BreakDurationGeneratorArguments.HalfOpenAttempts.get -> int
+Polly.CircuitBreaker.BreakDurationGeneratorArguments
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments() -> void
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments(double failureRate, int failureCount, Polly.ResilienceContext! context, Polly.Outcome outcome) -> void
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.BreakDurationGeneratorArguments(double failureRate, int failureCount, Polly.ResilienceContext! context, int halfOpenAttempts, Polly.Outcome outcome) -> void
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.Context.get -> Polly.ResilienceContext!
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureCount.get -> int
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.FailureRate.get -> double
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.HalfOpenAttempts.get -> int
+Polly.CircuitBreaker.BreakDurationGeneratorArguments.Outcome.get -> Polly.Outcome
Polly.CircuitBreaker.BrokenCircuitException
Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException() -> void
Polly.CircuitBreaker.BrokenCircuitException.BrokenCircuitException(string! message) -> void
@@ -41,7 +42,7 @@ Polly.CircuitBreaker.CircuitBreakerStrategyOptions.CircuitBreakerStrategyOptions
Polly.CircuitBreaker.CircuitBreakerStrategyOptions
Polly.CircuitBreaker.CircuitBreakerStrategyOptions.BreakDuration.get -> System.TimeSpan
Polly.CircuitBreaker.CircuitBreakerStrategyOptions.BreakDuration.set -> void
-Polly.CircuitBreaker.CircuitBreakerStrategyOptions.BreakDurationGenerator.get -> System.Func>?
+Polly.CircuitBreaker.CircuitBreakerStrategyOptions.BreakDurationGenerator.get -> System.Func, System.Threading.Tasks.ValueTask>?
Polly.CircuitBreaker.CircuitBreakerStrategyOptions.BreakDurationGenerator.set -> void
Polly.CircuitBreaker.CircuitBreakerStrategyOptions.CircuitBreakerStrategyOptions() -> void
Polly.CircuitBreaker.CircuitBreakerStrategyOptions.FailureRatio.get -> double
diff --git a/test/Polly.Core.Tests/CircuitBreaker/BreakDurationGeneratorArgumentsTests.cs b/test/Polly.Core.Tests/CircuitBreaker/BreakDurationGeneratorArgumentsTests.cs
index 7b0e5378559..6cf9cf10029 100644
--- a/test/Polly.Core.Tests/CircuitBreaker/BreakDurationGeneratorArgumentsTests.cs
+++ b/test/Polly.Core.Tests/CircuitBreaker/BreakDurationGeneratorArgumentsTests.cs
@@ -11,12 +11,14 @@ public void Constructor_Old_Ok()
double expectedFailureRate = 0.5;
int failureCount = 10;
var context = new ResilienceContext();
+ var outcome = Outcome.FromResult(42);
- var args = new BreakDurationGeneratorArguments(expectedFailureRate, failureCount, context);
+ var args = new BreakDurationGeneratorArguments(expectedFailureRate, failureCount, context, outcome);
args.FailureRate.Should().Be(expectedFailureRate);
args.FailureCount.Should().Be(failureCount);
args.Context.Should().Be(context);
+ args.Outcome.Should().Be(outcome);
}
[Fact]
@@ -25,12 +27,14 @@ public void Constructor_Ok()
double expectedFailureRate = 0.5;
int failureCount = 10;
var context = new ResilienceContext();
+ var outcome = Outcome.FromResult(42);
- var args = new BreakDurationGeneratorArguments(expectedFailureRate, failureCount, context, 99);
+ var args = new BreakDurationGeneratorArguments(expectedFailureRate, failureCount, context, 99, outcome);
args.FailureRate.Should().Be(expectedFailureRate);
args.FailureCount.Should().Be(failureCount);
args.Context.Should().Be(context);
args.HalfOpenAttempts.Should().Be(99);
+ args.Outcome.Should().Be(outcome);
}
}