How to enable Polly in an ASP.NET Core 2.0 Application
Last active
August 31, 2018 06:59
-
-
Save MovGP0/b50b138f8372c6ecba7b55157631e40d to your computer and use it in GitHub Desktop.
Using Polly for Retry Policies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Polly; | |
| using Polly.Registry; | |
| namespace MyApp.MyComponent | |
| { | |
| public sealed class MyService : IMyService | |
| { | |
| private static Serilog.ILogger Log => Serilog.Log.ForContext<MyService>(); | |
| public GetResource2MaximumParticipantsUoW(IReadOnlyPolicyRegistry<string> policyRegistry) | |
| { | |
| Policy = policyRegistry.GetAsyncPolicy<List<Resource2MaximumParticipants>>(PolicyNames.GetResource2MaximumParticipantsUoW); | |
| } | |
| private IAsyncPolicy<List<Resource2MaximumParticipants>> Policy { get; } | |
| public Task ExecuteAsync(CancellationToken cancellationToken) | |
| { | |
| var context = new Context(nameof(MyService)); | |
| // context["hash"] = parameter.GetHash(); | |
| return Policy.ExecuteAsync(_ => ExecuteInternalAsync(cancellationToken), context); | |
| } | |
| public Task ExecuteInternalAsync(CancellationToken cancellationToken) | |
| { | |
| //TODO: implement business logic here... | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Polly; | |
| using Polly.Caching; | |
| using Polly.Registry; | |
| namespace MyApp.MyComponent | |
| { | |
| public static class Policies | |
| { | |
| public static IPolicyRegistry<string> AddMyComponentPolicies(this IPolicyRegistry<string> registry, IServiceProvider serviceProvider) | |
| { | |
| var acp = serviceProvider.GetRequiredService<IAsyncCacheProvider>(); | |
| registry.Add(PolicyNames.MyService, Create_MyService_Policy(acp)); | |
| // TODO: register further policies here | |
| return registry; | |
| } | |
| private static IAsyncPolicy<TResult> Create_MyService_Policy<TResult>(IAsyncCacheProvider acp) | |
| { | |
| var fallback = Policy.NoOpAsync<TResult>(); | |
| var cache = Policy | |
| .CacheAsync<TResult>(acp, cacheDuration, context => context.OperationKey + context["hash"]); | |
| var retry = Policy | |
| .Handle<DbUpdateConcurrencyException>() | |
| .RetryAsync(); | |
| var breaker = Policy | |
| .Handle<DbUpdateConcurrencyException>() | |
| .AdvancedCircuitBreakerAsync(0.5, TimeSpan.FromSeconds(5), 20, TimeSpan.FromSeconds(30)); | |
| var bulkhead = Policy.BulkheadAsync<TResult>(12, 2); | |
| var timeout = Policy.TimeoutAsync<TResult>(TimeSpan.FromSeconds(5)); | |
| // must be in this exact order! | |
| return fallback.WrapAsync(cache).WrapAsync(retry).WrapAsync(breaker).WrapAsync(bulkhead).WrapAsync(timeout); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Microsoft.Extensions.DependencyInjection; | |
| using Polly.Caching; | |
| using Polly.Caching.Memory; | |
| using Polly.Registry; | |
| namespace MyApp | |
| { | |
| public static class PolicyFactory | |
| { | |
| public static IServiceCollection AddPolicies(this IServiceCollection services) | |
| { | |
| services.AddSingleton<IAsyncCacheProvider, MemoryCacheProvider>(); | |
| services.AddSingleton<IPolicyRegistry<string>, PolicyRegistry>(serviceProvider => | |
| { | |
| var registry = new PolicyRegistry(); | |
| registry.AddMyComponentPolicies(serviceProvider); | |
| // TODO: register additional components here | |
| return registry; | |
| }); | |
| services.AddTransient<IReadOnlyPolicyRegistry<string>>(e => e.GetRequiredService<IPolicyRegistry<string>>()); | |
| return services; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Diagnostics; | |
| using System.Runtime.CompilerServices; | |
| using Polly; | |
| using Polly.Registry; | |
| namespace MyApp | |
| { | |
| public static class PolicyRegistryExtensions | |
| { | |
| private static Serilog.ILogger Log => Serilog.Log.ForContext(typeof(PolicyRegistryExtensions)); | |
| [DebuggerStepThrough] | |
| public static IAsyncPolicy<T> GetAsyncPolicy<T>(this IReadOnlyPolicyRegistry<string> policyRegistry, string policyName, | |
| [CallerMemberName] string memberName = "", | |
| [CallerFilePath] string sourceFilePath = "", | |
| [CallerLineNumber] int sourceLineNumber = 0) | |
| { | |
| if (policyRegistry == null) throw new ArgumentNullException(nameof(policyRegistry)); | |
| if (policyName == null) throw new ArgumentNullException(nameof(policyName)); | |
| var policy = policyRegistry.Get<IAsyncPolicy<T>>(policyName); | |
| if (policy != null) return policy; | |
| // ReSharper disable ExplicitCallerInfoArgument | |
| Log.Here(memberName, sourceFilePath, sourceLineNumber) | |
| .Warning("No policy was registered with name {name}. Using Fallback.", policyName); | |
| // ReSharper restore ExplicitCallerInfoArgument | |
| return Policy.NoOpAsync<T>(); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace MyApp | |
| { | |
| public sealed class Startup | |
| { | |
| public Startup(IConfiguration configuration) | |
| { | |
| Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); | |
| } | |
| public IConfiguration Configuration { get; } | |
| // ReSharper disable once UnusedMember.Global | |
| public void ConfigureServices(IServiceCollection services) | |
| { | |
| services.AddPolicies(); | |
| // TODO: register additional services | |
| } | |
| // ReSharper disable once UnusedMember.Global | |
| public void Configure(IApplicationBuilder app, IHostingEnvironment env) | |
| { | |
| // TODO: setup application | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment