Polly is a C# implementation of elastic instantaneous error handling library
It can help us do some fault-tolerant mode processing, such as:
- Timeout and Retry
- Circuit Breaker
- Bulkhead Isolation
- Fallback
It is also very simple to use, such as:
// Retry multiple times, calling an action on each retry // with the current exception and retry count Policy .Handle<SomeExceptionType>() .Retry(3, onRetry: (exception, retryCount) => { // Add logic to be executed before each retry, such as logging });
But we have to write this in every place, and I still don't like it.
So how to simplify it?
Of course, we use these AOP frameworks to encapsulate what we commonly use to make Attribute
How to achieve simplification?
Let's try to make the Retry function RetryAttribute
1. Install the AOP framework
How tiring to write by yourself, how good it is to use ready-made ones
dotnet add package
2. Write Retry InterceptorAttribute
public class RetryAttribute : AbstractInterceptorAttribute { private readonly int retryCount; public RetryAttribute(int retryCount) { = retryCount; } public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next) { await <Exception>() .RetryAsync(retryCount) .ExecuteAsync(() => next(context)); } }
3. Considering that there is a difference between async and sync in Polly, let's be compatible.
public class RetryAttribute : AbstractInterceptorAttribute { private readonly int retryCount; public RetryAttribute(int retryCount) { = retryCount; } public override void Invoke(AspectContext context, AspectDelegate next) { <Exception>() .Retry(retryCount) .Execute(() => next(context)); } public override async Task InvokeAsync(AspectContext context, AsyncAspectDelegate next) { await <Exception>() .RetryAsync(retryCount) .ExecuteAsync(() => next(context)); } }
4. Let's do a test
public class RetryTest { public class DoRetryTest { public int Count { get; set; } [Retry(2)] // Use Retry public virtual void Do() { if (Count < 50) { Count++; // Add 1 for each call throw new FieldAccessException(); } } } public DoRetryTest Mock() { return new ServiceCollection() .AddTransient<DoRetryTest>() .ConfigureAop() .BuildServiceProvider() .GetRequiredService<DoRetryTest>(); } [Fact] public void RetryWhenSync() { var sut = Mock(); <FieldAccessException>(() => ()); (3, ); //We expect to call 3 times in total } }
Yes, that's it, we can use RetryAttribute anywhere
Of course, some common methods have been encapsulated
Here, by integrating Polly's various functions into more convenient functions
How to enable + Polly, just use EnablePolly()
like:
new ServiceCollection() .AddTransient<DoTimeoutTest>() .ConfigureAop(i => ())
TimeoutAttribute
[Timeout(seconds: 1)] // timeout 1 seconds, when timeout will throw TimeoutRejectedException double Wait(double seconds); [Timeout(timeSpan: "00:00:00.100")] // timeout 100 milliseconds, only work on async method when no CancellationToken async Task<double> WaitAsync(double seconds, CancellationToken cancellationToken = default); [Timeout(timeSpan: "00:00:01")] // timeout 1 seconds, but no work on async method when no CancellationToken async Task<double> NoCancellationTokenWaitAsync(double seconds);
RetryAttribute
[Retry(retryCount: 2, ExceptionType = typeof(AccessViolationException))] // retry 2 times when if throw Exception void Do()
CircuitBreakerAttribute
[CircuitBreaker(exceptionsAllowedBeforeBreaking: 3, durationOfBreak: "00:00:01")] //or [AdvancedCircuitBreaker(failureThreshold: 0.1, samplingDuration: "00:00:01", minimumThroughput: 3, durationOfBreak: "00:00:01")] void Do()
BulkheadAttribute
[Bulkhead(maxParallelization: 5, maxQueuingActions: 10)] void Do()
Related, you can check it out//zh-cn/
The above is the detailed content of how to use Polly in C#. For more information about using Polly in C#, please follow my other related articles!