Source-generated, zero-allocation resilience policies for .NET — Retry, Timeout, RateLimit, and CircuitBreaker as attributes on an interface.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Retry, timeout, rate limiting and circuit breaking for .NET, declared as attributes on an interface and compiled into a proxy: a source-generated alternative to Polly with no allocation on the happy path.
[Retry] and [CircuitBreaker], asserted by tests on every run. Polly v8 allocates a 64 B ResilienceContext per call.CancellationToken is a compiler diagnostic.dotnet add package ZeroAlloc.Resilience
using Microsoft.Extensions.DependencyInjection;
using ZeroAlloc.Resilience;
var services = new ServiceCollection();
services.AddWeatherClientResilience<FlakyWeatherClient>(); // generated: registers the proxy
var client = services.BuildServiceProvider().GetRequiredService<IWeatherClient>();
Console.WriteLine(await client.GetForecastAsync("Amsterdam", CancellationToken.None));
// Amsterdam: sunny, after 3 attempts
[Retry(MaxAttempts = 3, BackoffMs = 100, Jitter = true)]
[Timeout(Ms = 5_000)]
[CircuitBreaker(MaxFailures = 5, ResetMs = 30_000)]
public interface IWeatherClient
{
ValueTask<string> GetForecastAsync(string city, CancellationToken ct);
}
public sealed class FlakyWeatherClient : IWeatherClient
{
private int _calls;
public ValueTask<string> GetForecastAsync(string city, CancellationToken ct)
=> ++_calls < 3
? throw new HttpRequestException($"attempt {_calls} failed")
: ValueTask.FromResult($"{city}: sunny, after {_calls} attempts");
}
The first two calls throw, the proxy retries, and the caller only sees the result. Callers inject IWeatherClient as usual.
Result<T> and policy failures come back as a failure instead of a throw.Retry-After hints.Add{Service}Resilience<TImpl>() extension.Against Polly.Core 8.8.0 on .NET 10.0.13, measured 2026-10-21. Allocations are exact; speed is a same-run ratio.
| Operation | ZA vs Polly | Polly alloc | ZA alloc |
|---|---|---|---|
| Retry, happy path | 20.0× faster | 64 B | 0 B |
| CircuitBreaker, closed | 23.3× faster | 64 B | 0 B |
| All-policies stacked, happy path | 7.7× faster | 104 B | 144 B |
With all policies stacked, the 144 B is the linked CancellationTokenSource and timer that [Timeout] needs; without [Timeout] the proxy allocates nothing. Polly walks a delegate chain per call; ZA emits one method with the policy checks inline. Failure paths, an open circuit and the full method: docs/performance.md.