From 5e71c23a1443bbfded8894d03d9d45a8596a3ec7 Mon Sep 17 00:00:00 2001 From: Martin Costello <martin@martincostello.com> Date: Wed, 14 Apr 2021 18:31:27 +0100 Subject: [PATCH] Update Polly and support IConcurrentPolicyRegistry<string> (#31708) --- eng/Versions.props | 2 +- .../PollyServiceCollectionExtensions.cs | 26 ++++++--- .../PollyHttpClientBuilderExtensionsTest.cs | 55 +++++++++++++++++++ 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 3ae7ae758ab..5f33d247890 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -246,7 +246,7 @@ <NSwagApiDescriptionClientVersion>13.0.4</NSwagApiDescriptionClientVersion> <PlaywrightSharpVersion>0.192.0</PlaywrightSharpVersion> <PollyExtensionsHttpVersion>3.0.0</PollyExtensionsHttpVersion> - <PollyVersion>7.1.0</PollyVersion> + <PollyVersion>7.2.2</PollyVersion> <SeleniumSupportVersion>4.0.0-beta1</SeleniumSupportVersion> <SeleniumWebDriverChromeDriverVersion>89.0.4389.2300-beta</SeleniumWebDriverChromeDriverVersion> <SeleniumWebDriverVersion>4.0.0-beta1</SeleniumWebDriverVersion> diff --git a/src/HttpClientFactory/Polly/src/DependencyInjection/PollyServiceCollectionExtensions.cs b/src/HttpClientFactory/Polly/src/DependencyInjection/PollyServiceCollectionExtensions.cs index 6fe049d1172..c9e080c4faf 100644 --- a/src/HttpClientFactory/Polly/src/DependencyInjection/PollyServiceCollectionExtensions.cs +++ b/src/HttpClientFactory/Polly/src/DependencyInjection/PollyServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -8,15 +8,15 @@ using Polly.Registry; namespace Microsoft.Extensions.DependencyInjection { /// <summary> - /// Provides convenience extension methods to register <see cref="IPolicyRegistry{String}"/> and - /// <see cref="IReadOnlyPolicyRegistry{String}"/> in the service collection. + /// Provides convenience extension methods to register <see cref="IPolicyRegistry{String}"/> and + /// <see cref="IReadOnlyPolicyRegistry{String}"/> in the service collection. /// </summary> public static class PollyServiceCollectionExtensions { /// <summary> /// Registers an empty <see cref="PolicyRegistry"/> in the service collection with service types - /// <see cref="IPolicyRegistry{String}"/>, and <see cref="IReadOnlyPolicyRegistry{String}"/> and returns - /// the newly created registry. + /// <see cref="IPolicyRegistry{String}"/>, <see cref="IReadOnlyPolicyRegistry{String}"/>, and + /// <see cref="IConcurrentPolicyRegistry{String}"/> and returns the newly created registry. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <returns>The newly created <see cref="IPolicyRegistry{String}"/>.</returns> @@ -30,6 +30,8 @@ namespace Microsoft.Extensions.DependencyInjection // Create an empty registry, register and return it as an instance. This is the best way to get a // single instance registered using both interfaces. var registry = new PolicyRegistry(); + + services.AddSingleton<IConcurrentPolicyRegistry<string>>(registry); services.AddSingleton<IPolicyRegistry<string>>(registry); services.AddSingleton<IReadOnlyPolicyRegistry<string>>(registry); @@ -38,8 +40,8 @@ namespace Microsoft.Extensions.DependencyInjection /// <summary> /// Registers the provided <see cref="IPolicyRegistry{String}"/> in the service collection with service types - /// <see cref="IPolicyRegistry{String}"/>, and <see cref="IReadOnlyPolicyRegistry{String}"/> and returns - /// the provided registry. + /// <see cref="IPolicyRegistry{String}"/>, <see cref="IReadOnlyPolicyRegistry{String}"/>, and + /// <see cref="IConcurrentPolicyRegistry{String}"/> and returns the provided registry. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="registry">The <see cref="IPolicyRegistry{String}"/>.</param> @@ -59,13 +61,18 @@ namespace Microsoft.Extensions.DependencyInjection services.AddSingleton<IPolicyRegistry<string>>(registry); services.AddSingleton<IReadOnlyPolicyRegistry<string>>(registry); + if (registry is IConcurrentPolicyRegistry<string> concurrentRegistry) + { + services.AddSingleton<IConcurrentPolicyRegistry<string>>(concurrentRegistry); + } + return registry; } /// <summary> /// Registers an empty <see cref="PolicyRegistry"/> in the service collection with service types - /// <see cref="IPolicyRegistry{String}"/>, and <see cref="IReadOnlyPolicyRegistry{String}"/> and - /// uses the specified delegate to configure it. + /// <see cref="IPolicyRegistry{String}"/>, <see cref="IReadOnlyPolicyRegistry{String}"/>, and + /// <see cref="IConcurrentPolicyRegistry{String}"/> and uses the specified delegate to configure it. /// </summary> /// <param name="services">The <see cref="IServiceCollection"/>.</param> /// <param name="configureRegistry">A delegate that is used to configure an <see cref="IPolicyRegistry{String}"/>.</param> @@ -93,6 +100,7 @@ namespace Microsoft.Extensions.DependencyInjection return registry; }); + services.AddSingleton<IConcurrentPolicyRegistry<string>>(serviceProvider => serviceProvider.GetRequiredService<PolicyRegistry>()); services.AddSingleton<IPolicyRegistry<string>>(serviceProvider => serviceProvider.GetRequiredService<PolicyRegistry>()); services.AddSingleton<IReadOnlyPolicyRegistry<string>>(serviceProvider => serviceProvider.GetRequiredService<PolicyRegistry>()); diff --git a/src/HttpClientFactory/Polly/test/DependencyInjection/PollyHttpClientBuilderExtensionsTest.cs b/src/HttpClientFactory/Polly/test/DependencyInjection/PollyHttpClientBuilderExtensionsTest.cs index 94d3f82bfdf..0f30410379d 100644 --- a/src/HttpClientFactory/Polly/test/DependencyInjection/PollyHttpClientBuilderExtensionsTest.cs +++ b/src/HttpClientFactory/Polly/test/DependencyInjection/PollyHttpClientBuilderExtensionsTest.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Http; using Microsoft.Extensions.Http.Logging; using Polly; +using Polly.Registry; using Xunit; namespace Microsoft.Extensions.DependencyInjection @@ -468,6 +469,60 @@ namespace Microsoft.Extensions.DependencyInjection Assert.Equal(HttpStatusCode.Created, response.StatusCode); } + [Fact] + public void AddPolicyHandlerFromRegistry_WithoutConfigureDelegate_AddsPolicyRegistries() + { + var serviceCollection = new ServiceCollection(); + + // Act + serviceCollection.AddPolicyRegistry(); + + var services = serviceCollection.BuildServiceProvider(); + var registry = services.GetService<IPolicyRegistry<string>>(); + + // Assert + Assert.NotNull(registry); + Assert.Same(registry, services.GetService<IConcurrentPolicyRegistry<string>>()); + Assert.Same(registry, services.GetService<IReadOnlyPolicyRegistry<string>>()); + } + + [Fact] + public void AddPolicyHandlerFromRegistry_WithRegistry_AddsPolicyRegistries() + { + var serviceCollection = new ServiceCollection(); + var registry = new PolicyRegistry(); + + // Act + serviceCollection.AddPolicyRegistry(registry); + + var services = serviceCollection.BuildServiceProvider(); + + // Assert + Assert.Same(registry, services.GetService<IConcurrentPolicyRegistry<string>>()); + Assert.Same(registry, services.GetService<IPolicyRegistry<string>>()); + Assert.Same(registry, services.GetService<IReadOnlyPolicyRegistry<string>>()); + } + + [Fact] + public void AddPolicyHandlerFromRegistry_WithConfigureDelegate_AddsPolicyRegistries() + { + var serviceCollection = new ServiceCollection(); + + // Act + serviceCollection.AddPolicyRegistry((serviceProvider, registry) => + { + // No-op + }); + + var services = serviceCollection.BuildServiceProvider(); + var registry = services.GetService<IPolicyRegistry<string>>(); + + // Assert + Assert.NotNull(registry); + Assert.Same(registry, services.GetService<IConcurrentPolicyRegistry<string>>()); + Assert.Same(registry, services.GetService<IReadOnlyPolicyRegistry<string>>()); + } + // Throws an exception or fails on even numbered requests, otherwise succeeds. private class FaultyMessageHandler : DelegatingHandler { -- GitLab