CSharpEssentials.Resilience 5.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CSharpEssentials.Resilience --version 5.2.0
                    
NuGet\Install-Package CSharpEssentials.Resilience -Version 5.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CSharpEssentials.Resilience" Version="5.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CSharpEssentials.Resilience" Version="5.2.0" />
                    
Directory.Packages.props
<PackageReference Include="CSharpEssentials.Resilience" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CSharpEssentials.Resilience --version 5.2.0
                    
#r "nuget: CSharpEssentials.Resilience, 5.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CSharpEssentials.Resilience@5.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CSharpEssentials.Resilience&version=5.2.0
                    
Install as a Cake Addin
#tool nuget:?package=CSharpEssentials.Resilience&version=5.2.0
                    
Install as a Cake Tool

CSharpEssentials.Resilience

HTTP-agnostic resilience patterns (Retry, Timeout, Circuit Breaker, Fallback) with Result<T> integration. Composable ResiliencePolicy builder backed by Polly v8 (Polly.Core) for transient fault handling without exceptions.

Installation

dotnet add package CSharpEssentials.Resilience

Quick Start

using CSharpEssentials.Resilience;

// Simple retry
Result<User> user = await ResiliencePolicy
    .Create()
    .WithRetry(maxAttempts: 3, delay: TimeSpan.FromSeconds(1))
    .ExecuteAsync(_ => _db.GetUser(id));

// Retry + Timeout
Result<Order> order = await ResiliencePolicy
    .Create()
    .WithRetry(3)
    .WithTimeout(TimeSpan.FromSeconds(5))
    .ExecuteAsync(_ => _orderService.GetOrder(id));

// Circuit Breaker + Fallback (fallback needs the typed ResiliencePolicy<T>)
Result<Product> product = await ResiliencePolicy<Product>
    .Create()
    .WithCircuitBreaker(minimumThroughput: 10, failureRatio: 0.5)
    .WithFallback(ct => _cache.GetAsync<Product>(id, ct))
    .ExecuteAsync(_ => _productService.GetProduct(id));

Retrying Failed Results

Both ResiliencePolicy and ResiliencePolicy<T> retry exceptions and failed Result / Result<T> values. The circuit breaker counts the same failures. The non-generic ResiliencePolicy checks any return value that implements IResultBase; other return values count only when the delegate throws.

Errors of type Unauthorized, Forbidden, NotFound and Validation are not retried, because running the operation again gives the same answer. Every other failed result (Failure, Unexpected, Conflict, …) is treated as transient. When the retries run out, the last failed result is returned.

Result<Order> order = await ResiliencePolicy
    .Create()
    .WithRetry(maxAttempts: 3)
    .ExecuteAsync(ct => _orderService.TryGetOrder(id, ct)); // returns Result<Order>

Delegate Extensions

using CSharpEssentials.Resilience;

// Direct execution — wraps any Func<Task<T>> in a Result
Func<Task<User>> getUser = () => _db.GetUser(id);
Result<User> user = await getUser.ExecuteAsync();

// With CancellationToken
Func<CancellationToken, Task<User>> getUserWithToken = ct => _db.GetUser(id, ct);
Result<User> userWithToken = await getUserWithToken.ExecuteAsync(cancellationToken);

Result Retry

// Retry a failed Result directly
Func<CancellationToken, Task<Result<User>>> operation = ct => _db.TryGetUser(id, ct); // returns Result<User>
Result<User> result = await operation.RetryIfFailed(maxAttempts: 3, delay: TimeSpan.FromSeconds(1));

By default every failure is retried except Unauthorized, Forbidden, NotFound and Validation errors. Pass a shouldRetry predicate to decide yourself:

// Retry only errors you classify as transient
Result<User> result = await operation.RetryIfFailed(
    shouldRetry: error => error.Code == "Db.Timeout",
    maxAttempts: 3,
    delay: TimeSpan.FromSeconds(1));

The predicate replaces the default classification. An exception thrown by the operation is converted to the error that would be returned for it (ErrorType.Unexpected) and passed to the predicate too, so an exception the predicate rejects is not retried. Caller cancellation works as without a predicate: it is never retried and throws OperationCanceledException.

Configuration Options

using CSharpEssentials.Resilience;

// Use options records
var options = new ResiliencePolicyOptions
{
    Retry = new RetryOptions { MaxAttempts = 3, Delay = TimeSpan.FromSeconds(1) },
    Timeout = new TimeoutOptions { Timeout = TimeSpan.FromSeconds(5) },
    CircuitBreaker = new CircuitBreakerOptions
    {
        MinimumThroughput = 10,
        FailureRatio = 0.5,
        BreakDuration = TimeSpan.FromSeconds(30)
    }
};

Result<User> user = await ResiliencePolicy
    .Create(options)
    .ExecuteAsync(_ => _db.GetUser(id));

Error Handling

Resilience-specific errors are returned as Error values:

  • Error.Failure("Resilience.Timeout", "Operation timed out.")
  • Error.Failure("Resilience.CircuitBroken", "Circuit breaker is open.")

When retries exhaust, the last exception is returned as ErrorType.Unexpected.

Cancellation of the caller's token is not converted to an error. When the CancellationToken passed to ExecuteAsync or RetryIfFailed is cancelled and the operation throws OperationCanceledException, the exception is rethrown and WithFallback does not run the fallback. If the caller cancels after an attempt returned a retryable failed Result, ExecuteAsync, RetryIfFailed and WithFallback throw OperationCanceledException instead of returning that result. This is the same whether the cancel lands during an attempt or during the backoff delay, and it also applies right after the final attempt: cancellation wins over returning the last failed result. It also applies to policies without a retry strategy, such as a circuit-breaker-only or timeout-only policy. This rule covers returned failures only: if the operation throws an exception other than OperationCanceledException while the caller's token is cancelled, the exception is returned as an Unexpected error. An OperationCanceledException from another token, such as an HttpClient timeout, is treated as a normal failure: it is retried and it triggers the fallback.

A default(ResiliencePolicy) or default(ResiliencePolicy<T>) behaves like Create().

Pipeline Composition

// Stack multiple policies
Result<Data> result = await ResiliencePolicy
    .Create()
    .WithRetry(3)
    .WithTimeout(TimeSpan.FromSeconds(5))
    .WithCircuitBreaker(minimumThroughput: 10)
    .ExecuteAsync(_ => _api.GetData());

Polly Integration

Under the hood, uses the Polly v8 ResiliencePipeline from the Polly.Core package. The package does not reference the full Polly package; add it yourself if you use the Polly v7 API (Policy, AsyncRetryPolicy, …).

// Advanced: Direct Polly configuration
using Polly;
using Polly.Retry;

Result<Data> result = await ResiliencePolicy
    .Create(builder =>
    {
        builder.AddRetry(new RetryStrategyOptions
        {
            MaxRetryAttempts = 3,
            Delay = TimeSpan.FromSeconds(1),
            BackoffType = DelayBackoffType.Exponential
        });
    })
    .ExecuteAsync(_ => _api.GetData());
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 is compatible.  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 is compatible.  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.  net11.0 is compatible. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on CSharpEssentials.Resilience:

Package Downloads
CSharpEssentials.GcpSecretManager

A powerful .NET configuration provider for Google Cloud Secret Manager that enables seamless secret management in your applications. Features include region-specific secret handling, flexible filtering options, batch processing, automatic secret rotation, built-in retry policies, and JSON value flattening support. Perfect for cloud-native applications requiring secure and scalable secret management.

CSharpEssentials.Http

HttpClient extensions that bridge HTTP calls to the Result pattern. Provides GetFromJsonAsResultAsync, PostAsJsonAsResultAsync, status code mapping, and Polly resilience integration.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
6.5.2 133 10/10/2026
6.5.1 138 10/10/2026
6.5.0 140 10/9/2026
6.4.0 136 10/9/2026
6.3.0 160 10/8/2026
6.2.0 175 10/8/2026
6.1.0 178 10/7/2026
6.0.0 183 10/7/2026
5.2.1 173 10/7/2026
5.2.0 175 10/7/2026
5.1.0 162 10/7/2026
5.0.0 173 10/6/2026
4.1.0 166 10/6/2026
4.0.0 182 10/5/2026
3.2.3 311 5/31/2026
3.2.2 199 5/31/2026
3.2.1 192 5/31/2026
3.2.0 182 5/30/2026