Skip to main content

Resilience

Vali-Mediator.Resilience provides a fluent, composable resilience pipeline with zero external dependencies.

Installation

dotnet add package Vali-Mediator.Resilience

Execution Order

When multiple policies are combined, they execute in this fixed order (outermost → innermost):

loading...

Fallback is always the outermost — it catches failures from all inner policies. Hedge is innermost — it runs the actual operation (potentially in parallel).

Creating a Policy

var policy = ResiliencePolicy.Create()
.Retry(3)
.CircuitBreaker(opts =>
{
opts.FailureThreshold = 5;
opts.BreakDuration = TimeSpan.FromSeconds(30);
})
.Timeout(TimeSpan.FromSeconds(10))
.Build();

// Execute
string result = await policy.ExecuteAsync<string>(async ct =>
{
return await _httpClient.GetStringAsync(url, ct);
});

Resilience Presets

Pre-configured policies for common scenarios:

// For external API calls (Retry + CircuitBreaker + Timeout)
var policy = ResiliencePresets.ForExternalApi();

// For database operations (Retry with shorter timeout)
var policy = ResiliencePresets.ForDatabase();

// For critical operations (Retry + CircuitBreaker + Fallback)
var policy = ResiliencePresets.ForCritical(fallbackValue: "default");

// No resilience (passthrough)
var policy = ResiliencePresets.NoResilience();

Available Policies

PolicyMethodPurpose
Retry.Retry(n)Retry on transient failures
Circuit Breaker.CircuitBreaker(opts)Stop calls when failure rate is high
Timeout.Timeout(ts)Cancel slow operations
Bulkhead.Bulkhead(n, q)Limit concurrent requests
Hedge.Hedge(delay)Parallel speculative requests
Rate Limiter.RateLimiter(cap)Throttle request rate
Chaos.Chaos(rate)Inject faults for testing
Fallback.Fallback<T>(opts)Return a default when all else fails

Void Operations

All policies support void (no return value) operations:

await policy.ExecuteAsync(async ct =>
{
await _repository.SaveAsync(entity, ct);
});

Named Policies (Shared Circuit Breaker State)

Use a key to share state across multiple policy instances:

var policy = ResiliencePolicy.Create("payment-service")
.CircuitBreaker(opts =>
{
opts.CircuitKey = "payment-circuit"; // shared state key
opts.FailureThreshold = 5;
})
.Build();