AdvancedCircuitController
using Polly.Utilities;
using System;
namespace Polly.CircuitBreaker
{
internal class AdvancedCircuitController : CircuitStateController
{
private const short NumberOfWindows = 10;
internal static readonly long ResolutionOfCircuitTimer = TimeSpan.FromMilliseconds(20).Ticks;
private readonly IHealthMetrics _metrics;
private readonly double _failureThreshold;
private readonly int _minimumThroughput;
public AdvancedCircuitController(double failureThreshold, TimeSpan samplingDuration, int minimumThroughput, TimeSpan durationOfBreak, Action<Exception, TimeSpan, Context> onBreak, Action<Context> onReset, Action onHalfOpen)
: base(durationOfBreak, onBreak, onReset, onHalfOpen)
{
object metrics;
if (samplingDuration.Ticks >= ResolutionOfCircuitTimer * 10) {
IHealthMetrics healthMetrics = new RollingHealthMetrics(samplingDuration, 10);
metrics = healthMetrics;
} else {
IHealthMetrics healthMetrics = new SingleHealthMetrics(samplingDuration);
metrics = healthMetrics;
}
_metrics = (IHealthMetrics)metrics;
_failureThreshold = failureThreshold;
_minimumThroughput = minimumThroughput;
}
public override void OnCircuitReset(Context context)
{
using (TimedLock.Lock(_lock)) {
if (_metrics != null)
_metrics.Reset_NeedsLock();
ResetInternal_NeedsLock(context);
}
}
public override void OnActionSuccess(Context context)
{
using (TimedLock.Lock(_lock)) {
if (_circuitState == CircuitState.HalfOpen)
OnCircuitReset(context);
_metrics.IncrementSuccess_NeedsLock();
}
}
public override void OnActionFailure(Exception ex, Context context)
{
using (TimedLock.Lock(_lock)) {
_lastException = ex;
if (_circuitState == CircuitState.HalfOpen)
Break_NeedsLock(context);
else {
_metrics.IncrementFailure_NeedsLock();
HealthCount healthCount_NeedsLock = _metrics.GetHealthCount_NeedsLock();
int total = healthCount_NeedsLock.Total;
if (total >= _minimumThroughput && (double)healthCount_NeedsLock.Failures / (double)total >= _failureThreshold)
Break_NeedsLock(context);
}
}
}
}
}