// Inner exceptions of ordinary exceptions or AggregateException, with or without conditions Policy .HandleInner<HttpRequestException>() .OrInner<OperationCanceledException>(ex => ex.CancellationToken != myToken)
// Retry once Policy .Handle<SomeExceptionType>() .Retry()
// Retry multiple times Policy .Handle<SomeExceptionType>() .Retry(3)
// Retry multiple times, calling an action on each retry // with the current exception and retry count Policy .Handle<SomeExceptionType>() .Retry(3, (exception, retryCount) => { // do something });
// Retry multiple times, calling an action on each retry // with the current exception, retry count and context // provided to Execute() Policy .Handle<SomeExceptionType>() .Retry(3, (exception, retryCount, context) => { // do something });
// Retry forever, calling an action on each retry with the // current exception Policy .Handle<SomeExceptionType>() .RetryForever(exception => { // do something });
// Retry forever, calling an action on each retry with the // current exception and context provided to Execute() Policy .Handle<SomeExceptionType>() .RetryForever((exception, context) => { // do something });
// Retry, waiting a specified duration between each retry Policy .Handle<SomeExceptionType>() .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) });
// Retry, waiting a specified duration between each retry, // calling an action on each retry with the current exception // and duration Policy .Handle<SomeExceptionType>() .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }, (exception, timeSpan) => { // do something });
// Retry, waiting a specified duration between each retry, // calling an action on each retry with the current exception, // duration and context provided to Execute() Policy .Handle<SomeExceptionType>() .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }, (exception, timeSpan, context) => { // do something });
// Retry, waiting a specified duration between each retry, // calling an action on each retry with the current exception, // duration, retry count, and context provided to Execute() Policy .Handle<SomeExceptionType>() .WaitAndRetry(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3) }, (exception, timeSpan, retryCount, context) => { // do something });
// Retry a specified number of times, using a function to // calculate the duration to wait between retries based on // the current retry attempt (allows for exponential backoff) // In this case will wait for // 2 ^ 1 = 2 seconds then // 2 ^ 2 = 4 seconds then // 2 ^ 3 = 8 seconds then // 2 ^ 4 = 16 seconds then // 2 ^ 5 = 32 seconds Policy .Handle<SomeExceptionType>() .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) );
// Retry a specified number of times, using a function to // calculate the duration to wait between retries based on // the current retry attempt, calling an action on each retry // with the current exception, duration and context provided // to Execute() Policy .Handle<SomeExceptionType>() .WaitAndRetry( 5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timeSpan, context) => { // do something } );
// Retry a specified number of times, using a function to // calculate the duration to wait between retries based on // the current retry attempt, calling an action on each retry // with the current exception, duration, retry count, and context // provided to Execute() Policy .Handle<SomeExceptionType>() .WaitAndRetry( 5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timeSpan, retryCount, context) => { // do something } );
// Wait and retry forever, calling an action on each retry with the // current exception and the time to wait Policy .Handle<SomeExceptionType>() .WaitAndRetryForever( retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timespan) => { // do something });
// Wait and retry forever, calling an action on each retry with the // current exception, time to wait, and context provided to Execute() Policy .Handle<SomeExceptionType>() .WaitAndRetryForever( retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (exception, timespan, context) => { // do something });
// Break the circuit after the specified number of consecutive exceptions // and keep circuit broken for the specified duration, // calling an action on change of circuit state, // passing a context provided to Execute(). Action<Exception, TimeSpan, Context> onBreak = (exception, timespan, context) => { ... }; Action<Context> onReset = context => { ... }; CircuitBreakerPolicy breaker = Policy .Handle<SomeExceptionType>() .CircuitBreaker(2, TimeSpan.FromMinutes(1), onBreak, onReset);
// Monitor the circuit state, for example for health reporting. CircuitState state = breaker.CircuitState;
/* Closed 关闭状态,允许执行 Open 自动打开,执行会被阻断 Isolate 手动打开,执行会被阻断 HalfOpen 从自动打开状态恢复中,在熔断时间到了之后从Open状态切换到Closed */
// Execute a function returning a result var policy = Policy .Handle<SomeExceptionType>() .Retry();
var result = policy.Execute(() => DoSomething());
// Execute a function returning a result passing arbitrary context data var policy = Policy .Handle<SomeExceptionType>() .Retry(3, (exception, retryCount, context) => { object methodThatRaisedException = context["methodName"]; Log(exception, methodThatRaisedException) });
var result = policy.Execute( () => DoSomething(), new Dictionary<string, object>() {{ "methodName", "some method" }} );
// Timeout and return to the caller after 30 seconds, if the executed delegate has not completed. // Optimistic timeout: Delegates should take and honour a CancellationToken. Policy .Timeout(30)
// Configure timeout as timespan. Policy .Timeout(TimeSpan.FromMilliseconds(2500))
// Configure variable timeout via a func provider. Policy .Timeout(() => myTimeoutProvider)) // Func<TimeSpan> myTimeoutProvider
// Timeout, calling an action if the action times out Policy .Timeout(30, onTimeout: (context, timespan, task) => { // do something });
// Eg timeout, logging that the execution timed out: Policy .Timeout(30, onTimeout: (context, timespan, task) => { logger.Warn($"{context.PolicyKey} at {context.ExecutionKey}: execution timed out after {timespan.TotalSeconds} seconds."); });
// Eg timeout, capturing any exception from the timed-out task when it completes: Policy .Timeout(30, onTimeout: (context, timespan, task) => { task.ContinueWith(t => { if (t.IsFaulted) logger.Error($"{context.PolicyKey} at {context.ExecutionKey}: execution timed out after {timespan.TotalSeconds} seconds, with: {t.Exception}."); }); });
Policy timeoutPolicy = Policy.TimeoutAsync(30); HttpResponseMessage httpResponse = await timeoutPolicy .ExecuteAsync( async ct => await httpClient.GetAsync(endpoint, ct), // Execute a delegate which responds to a CancellationToken input parameter. CancellationToken.None // In this case, CancellationToken.None is passed into the execution, indicating you have no independent cancellation // control you wish to add to the cancellation provided by TimeoutPolicy. Your own indepdent CancellationToken can also // be passed - see wiki for examples. );
CancellationTokenSource userCancellationSource = new CancellationTokenSource(); // userCancellationSource perhaps hooked up to the user clicking a 'cancel' button, or other independent cancellation
HttpResponseMessage httpResponse = await _timeoutPolicy .ExecuteAsync( async ct => await httpClient.GetAsync(requestEndpoint, ct), userCancellationSource.Token ); // GetAsync(...) will be cancelled when either the timeout occurs, or userCancellationSource is signalled.
// Monitor the bulkhead available capacity, for example for health/load reporting. var bulkhead = Policy.Bulkhead(12, 2); // ... int freeExecutionSlots = bulkhead.BulkheadAvailableCount; int freeQueueSlots = bulkhead.QueueAvailableCount;
缓存 Cache
1 2 3 4 5 6 7
Microsoft.Extensions.Caching.Memory.IMemoryCache memoryCache = new Microsoft.Extensions.Caching.Memory.MemoryCache(new Microsoft.Extensions.Caching.Memory.MemoryCacheOptions()); Polly.Caching.Memory.MemoryCacheProvider memoryCacheProvider = new Polly.Caching.Memory.MemoryCacheProvider(memoryCache);
// (2) Create a Polly cache policy using that Polly.Caching.Memory.MemoryCacheProvider instance. var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5));
// Define a combined policy strategy, built of previously-defined policies. var policyWrap = Policy .Wrap(fallback, cache, retry, breaker, timeout, bulkhead); // (wraps the policies around any executed delegate: fallback outermost ... bulkhead innermost) policyWrap.Execute(...)
// Define a standard resilience strategy ... PolicyWrap commonResilience = Policy.Wrap(retry, breaker, timeout);
// ... then wrap in extra policies specific to a call site, at that call site: Avatar avatar = Policy .Handle<Whatever>() .Fallback<Avatar>(Avatar.Blank) .Wrap(commonResilience) .Execute(() => { /* get avatar */ });
// Share commonResilience, but wrap different policies in at another call site: Reputation reps = Policy .Handle<Whatever>() .Fallback<Reputation>(Reputation.NotAvailable) .Wrap(commonResilience) .Execute(() => { /* get reputation */ });
var policyResult = Policy .Handle<HttpRequestException>() .RetryAsync() .ExecuteAndCaptureAsync(() => DoSomethingAsync()); /* policyResult.Outcome - whether the call succeeded or failed policyResult.FinalException - the final exception captured, will be null if the call succeeded policyResult.ExceptionType - was the final exception an exception the policy was defined to handle (like HttpRequestException above) or an unhandled one (say Exception). Will be null if the call succeeded. policyResult.Result - if executing a func, the result if the call succeeded or the type's default value */