diff --git a/eng/Versions.props b/eng/Versions.props index 3ae7ae758ab6a681ac2faa4ddf84793f9e8495b6..5f33d2478909a3749125219f0ab5039002839bca 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 6fe049d1172460482752207ad4aea9d534ceaf63..c9e080c4faf908eed3aad2116a35cc5b5f02002a 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 94d3f82bfdf24c006ca9ed93c0c0df965185f861..0f30410379def408f110daee4ca71456b162210c 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 {