Philiprehberger.CircuitBreaker
0.2.1
dotnet add package Philiprehberger.CircuitBreaker --version 0.2.1
NuGet\Install-Package Philiprehberger.CircuitBreaker -Version 0.2.1
<PackageReference Include="Philiprehberger.CircuitBreaker" Version="0.2.1" />
<PackageVersion Include="Philiprehberger.CircuitBreaker" Version="0.2.1" />
<PackageReference Include="Philiprehberger.CircuitBreaker" />
paket add Philiprehberger.CircuitBreaker --version 0.2.1
#r "nuget: Philiprehberger.CircuitBreaker, 0.2.1"
#:package Philiprehberger.CircuitBreaker@0.2.1
#addin nuget:?package=Philiprehberger.CircuitBreaker&version=0.2.1
#tool nuget:?package=Philiprehberger.CircuitBreaker&version=0.2.1
Philiprehberger.CircuitBreaker
Standalone circuit breaker with sliding window failure rate, fallback support, half-open probing, and event callbacks.
Installation
dotnet add package Philiprehberger.CircuitBreaker
Usage
using Philiprehberger.CircuitBreaker;
var breaker = new CircuitBreaker(failureThreshold: 3, openDuration: TimeSpan.FromSeconds(10));
breaker.OnOpen = () => Console.WriteLine("Circuit opened!");
breaker.OnClose = () => Console.WriteLine("Circuit closed.");
breaker.OnHalfOpen = () => Console.WriteLine("Circuit half-open, probing...");
var result = breaker.Execute(() => ComputeValue());
var data = await breaker.ExecuteAsync(() => httpClient.GetStringAsync("/api/health"));
Sliding Window Failure Rate
Track the last N results and open the circuit when the failure rate exceeds a threshold, rather than requiring consecutive failures.
var options = new CircuitBreakerOptions(
FailureThreshold: 50,
SlidingWindowSize: 100,
FailureRateThreshold: 0.5
);
var breaker = new CircuitBreaker(options);
Fallback Support
Provide a fallback that runs when the circuit is open instead of throwing CircuitBrokenException.
var result = breaker.Execute(
() => CallRemoteService(),
() => GetCachedValue()
);
var data = await breaker.ExecuteAsync(
() => httpClient.GetStringAsync("/api/data"),
() => Task.FromResult("{\"fallback\": true}")
);
Success Threshold in Half-Open
Require multiple consecutive successes in half-open state before closing the circuit.
var options = new CircuitBreakerOptions(
FailureThreshold: 5,
OpenDuration: TimeSpan.FromSeconds(30),
SuccessThresholdInHalfOpen: 3
);
var breaker = new CircuitBreaker(options);
Jitter on Open Duration
Add random jitter to the open duration to prevent thundering herd when multiple circuit breakers recover simultaneously.
var options = new CircuitBreakerOptions(
FailureThreshold: 5,
OpenDuration: TimeSpan.FromSeconds(30),
JitterRatio: 0.2
);
var breaker = new CircuitBreaker(options);
Manual Control
breaker.Trip(); // Force the circuit open
breaker.Reset(); // Force the circuit closed
Handling Rejected Requests
try
{
var result = breaker.Execute(() => CallService());
}
catch (CircuitBrokenException ex)
{
Console.WriteLine($"State: {ex.State}, retry in {ex.RemainingDuration.TotalSeconds}s");
}
API
CircuitBreaker
| Member | Description |
|---|---|
CircuitBreaker(int failureThreshold = 5, TimeSpan? openDuration = null) |
Creates a new circuit breaker |
CircuitBreaker(CircuitBreakerOptions options) |
Creates a circuit breaker from options |
Execute<T>(Func<T>) |
Executes a synchronous operation through the breaker |
Execute<T>(Func<T>, Func<T>) |
Executes with a fallback when the circuit is open |
ExecuteAsync<T>(Func<Task<T>>) |
Executes an asynchronous operation through the breaker |
ExecuteAsync<T>(Func<Task<T>>, Func<Task<T>>) |
Executes async with a fallback when the circuit is open |
Trip() |
Manually opens the circuit |
Reset() |
Manually closes the circuit and resets failure count |
State |
Current CircuitState (Closed, Open, HalfOpen) |
FailureCount |
Number of consecutive failures |
LastFailure |
Timestamp of the most recent failure |
OnOpen |
Callback when circuit opens |
OnClose |
Callback when circuit closes |
OnHalfOpen |
Callback when circuit enters half-open |
OnFailure |
Callback on each failure |
OnSuccess |
Callback on each success |
CircuitBreakerOptions
| Property | Type | Default | Description |
|---|---|---|---|
FailureThreshold |
int |
5 |
Consecutive failures before opening |
OpenDuration |
TimeSpan? |
null (30s) |
Duration circuit stays open |
HalfOpenTimeout |
TimeSpan? |
null |
Timeout for half-open probe |
SlidingWindowSize |
int |
100 |
Number of results to track (0 to disable) |
FailureRateThreshold |
double |
0.5 |
Failure rate (0.0-1.0) that triggers open |
SuccessThresholdInHalfOpen |
int |
1 |
Consecutive successes to close from half-open |
JitterRatio |
double |
0.0 |
Random jitter on open duration (0.0-1.0) |
CircuitState
| Value | Description |
|---|---|
Closed |
Requests flow through normally |
Open |
Requests are rejected immediately |
HalfOpen |
Probe requests test whether the service has recovered |
CircuitBrokenException
| Property | Description |
|---|---|
State |
Circuit state when the exception was thrown |
OpenedAt |
When the circuit was opened |
RemainingDuration |
Time until the circuit transitions to half-open |
Development
dotnet build src/Philiprehberger.CircuitBreaker.csproj --configuration Release
Support
If you find this project useful:
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.