Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Polly to latest version #4340

Merged
merged 4 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static ServiceProvider InitializeServiceProvider(params HedgingClientType
private static void AddHedging(this IServiceCollection services, HedgingClientType clientType)
{
var clientBuilder = services.AddHttpClient(clientType.ToString(), client => client.Timeout = Timeout.InfiniteTimeSpan);
var hedgingBuilder = clientBuilder.AddStandardHedgingHandler().SelectStrategyByAuthority(SimpleClassifications.PublicData);
var hedgingBuilder = clientBuilder.AddStandardHedgingHandler().SelectPipelineByAuthority(SimpleClassifications.PublicData);
_ = clientBuilder.AddHttpMessageHandler<NoRemoteCallHandler>();

if (clientType.HasFlag(HedgingClientType.NoRoutes))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ namespace Microsoft.Extensions.Resilience.Bench;
public class ResilienceEnrichmentBenchmark
{
private MeterListener? _listener;
private ResilienceStrategy? _strategy;
private ResilienceStrategy? _strategyEnriched;
private ResiliencePipeline? _pipeline;
private ResiliencePipeline? _pipelineEnriched;

[GlobalSetup]
public void GlobalSetup()
{
_listener = MeteringUtil.ListenPollyMetrics();
_strategy = CreateResilienceStrategy(_ => { });
_strategyEnriched = CreateResilienceStrategy(services =>
_pipeline = CreateResiliencePipeline(_ => { });
_pipelineEnriched = CreateResiliencePipeline(services =>
{
services.AddResilienceEnrichment();
services.ConfigureFailureResultContext<string>(res => FailureResultContext.Create("dummy", "dummy", "dummy"));
Expand All @@ -35,21 +35,21 @@ public void GlobalSetup()
public void Cleanup() => _listener?.Dispose();

[Benchmark(Baseline = true)]
public void ReportTelemetry() => _strategy!.Execute(() => "dummy-result");
public void ReportTelemetry() => _pipeline!.Execute(() => "dummy-result");

[Benchmark]
public void ReportTelemetry_Enriched() => _strategyEnriched!.Execute(() => "dummy-result");
public void ReportTelemetry_Enriched() => _pipelineEnriched!.Execute(() => "dummy-result");

private static ResilienceStrategy CreateResilienceStrategy(Action<IServiceCollection> configure)
private static ResiliencePipeline CreateResiliencePipeline(Action<IServiceCollection> configure)
{
var services = new ServiceCollection();
services.AddLogging();
services.AddExceptionSummarizer();
services.AddResilienceStrategy("my-strategy", builder => builder.AddStrategy(context => new DummyStrategy(context.Telemetry), new DummyOptions()));
services.AddResiliencePipeline("my-pipeline", builder => builder.AddStrategy(context => new DummyStrategy(context.Telemetry), new DummyOptions()));
services.AddLogging();
configure(services);

return services.BuildServiceProvider().GetRequiredService<ResilienceStrategyProvider<string>>().GetStrategy("my-strategy");
return services.BuildServiceProvider().GetRequiredService<ResiliencePipelineProvider<string>>().GetPipeline("my-pipeline");
}

private class DummyStrategy : ResilienceStrategy
Expand Down
8 changes: 4 additions & 4 deletions eng/packages/General.props
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
<PackageVersion Include="Polly.Contrib.Simmy" Version="0.3.0" />
<PackageVersion Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
<PackageVersion Include="Polly.Core" Version="8.0.0-alpha.8" />
<PackageVersion Include="Polly.Extensions" Version="8.0.0-alpha.8" />
<PackageVersion Include="Polly.RateLimiting" Version="8.0.0-alpha.8" />
<PackageVersion Include="Polly" Version="8.0.0-alpha.8" />
<PackageVersion Include="Polly.Core" Version="8.0.0-beta.1" />
<PackageVersion Include="Polly.Extensions" Version="8.0.0-beta.1" />
<PackageVersion Include="Polly.RateLimiting" Version="8.0.0-beta.1" />
<PackageVersion Include="Polly" Version="8.0.0-beta.1" />
<PackageVersion Include="System.Buffers" Version="4.5.1" />
<PackageVersion Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageVersion Include="System.CommandLine.NamingConventionBinder" Version="2.0.0-beta4.22272.1" />
Expand Down
2 changes: 1 addition & 1 deletion eng/packages/TestOnly.props
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.3" />
<PackageVersion Include="Moq.AutoMock" Version="3.1.0" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="Polly.Testing" Version="8.0.0-alpha.8" />
<PackageVersion Include="Polly.Testing" Version="8.0.0-beta.1" />
<PackageVersion Include="StrongNamer" Version="0.2.5" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="$(SystemConfigurationConfigurationManagerVersion)" />
<PackageVersion Include="Xunit.Combinatorial" Version="1.5.25" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class HedgingEndpointOptions
[ValidateObjectMembers]
public HttpRateLimiterStrategyOptions RateLimiterOptions { get; set; } = new HttpRateLimiterStrategyOptions
{
Name = StandardHedgingStrategyNames.RateLimiter
Name = StandardHedgingPipelineNames.RateLimiter
};

/// <summary>
Expand All @@ -40,7 +40,7 @@ public class HedgingEndpointOptions
[ValidateObjectMembers]
public HttpCircuitBreakerStrategyOptions CircuitBreakerOptions { get; set; } = new HttpCircuitBreakerStrategyOptions
{
Name = StandardHedgingStrategyNames.CircuitBreaker
Name = StandardHedgingPipelineNames.CircuitBreaker
};

/// <summary>
Expand All @@ -55,6 +55,6 @@ public class HedgingEndpointOptions
public HttpTimeoutStrategyOptions TimeoutOptions { get; set; } = new()
{
Timeout = TimeSpan.FromSeconds(10),
Name = StandardHedgingStrategyNames.AttemptTimeout
Name = StandardHedgingPipelineNames.AttemptTimeout
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static partial class HttpClientBuilderExtensions
/// The standard hedging uses a pool of circuit breakers to ensure that unhealthy endpoints are not hedged against.
/// By default, the selection from pool is based on the URL Authority (scheme + host + port).
/// It is recommended that you configure the way the strategies are selected by calling
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectStrategyByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/>
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectPipelineByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/>
/// extensions.
/// <para>
/// See <see cref="HttpStandardHedgingResilienceOptions"/> for more details about the used resilience strategies.
Expand Down Expand Up @@ -63,7 +63,7 @@ public static IStandardHedgingHandlerBuilder AddStandardHedgingHandler(this IHtt
/// The standard hedging uses a pool of circuit breakers to ensure that unhealthy endpoints are not hedged against.
/// By default, the selection from pool is based on the URL Authority (scheme + host + port).
/// It is recommended that you configure the way the strategies are selected by calling
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectStrategyByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/>
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectPipelineByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/>
/// extensions.
/// <para>
/// See <see cref="HttpStandardHedgingResilienceOptions"/> for more details about the used resilience strategies.
Expand All @@ -82,7 +82,7 @@ public static IStandardHedgingHandlerBuilder AddStandardHedgingHandler(this IHtt
_ = builder.Services.AddOptionsWithValidateOnStart<HttpStandardHedgingResilienceOptions, HttpStandardHedgingResilienceOptionsCustomValidator>(optionsName);
_ = builder.Services.PostConfigure<HttpStandardHedgingResilienceOptions>(optionsName, options =>
{
options.HedgingOptions.HedgingActionGenerator = args =>
options.HedgingOptions.ActionGenerator = args =>
{
if (!args.PrimaryContext.Properties.TryGetValue(ResilienceKeys.RequestSnapshot, out var snapshot))
{
Expand All @@ -94,9 +94,9 @@ public static IStandardHedgingHandlerBuilder AddStandardHedgingHandler(this IHtt
// replace the request message
args.ActionContext.Properties.Set(ResilienceKeys.RequestMessage, requestMessage);

if (args.PrimaryContext.Properties.TryGetValue(ResilienceKeys.RoutingStrategy, out var routingStrategy))
if (args.PrimaryContext.Properties.TryGetValue(ResilienceKeys.RoutingStrategy, out var routingPipeline))
{
if (!routingStrategy.TryGetNextRoute(out var route))
if (!routingPipeline.TryGetNextRoute(out var route))
{
// no routes left, stop hedging
return null;
Expand All @@ -117,8 +117,8 @@ public static IStandardHedgingHandlerBuilder AddStandardHedgingHandler(this IHtt
var routingOptions = context.GetOptions<RequestRoutingOptions>(routingBuilder.Name);

_ = builder
.AddStrategy(new RoutingResilienceStrategy(routingOptions.RoutingStrategyProvider))
.AddStrategy(new RequestMessageSnapshotStrategy())
.AddStrategy(_ => new RoutingResilienceStrategy(routingOptions.RoutingStrategyProvider), new EmptyResilienceStrategyOptions())
.AddStrategy(_ => new RequestMessageSnapshotStrategy(), new EmptyResilienceStrategyOptions())
.AddTimeout(options.TotalRequestTimeoutOptions)
.AddHedging(options.HedgingOptions);
});
Expand All @@ -136,7 +136,7 @@ public static IStandardHedgingHandlerBuilder AddStandardHedgingHandler(this IHtt
.AddCircuitBreaker(options.EndpointOptions.CircuitBreakerOptions)
.AddTimeout(options.EndpointOptions.TimeoutOptions);
})
.SelectStrategyByAuthority(DataClassification.Unknown);
.SelectPipelineByAuthority(DataClassification.Unknown);

return new StandardHedgingHandlerBuilder(builder.Name, builder.Services, routingBuilder);
}
Expand All @@ -145,4 +145,8 @@ private record StandardHedgingHandlerBuilder(
string Name,
IServiceCollection Services,
IRoutingStrategyBuilder RoutingStrategyBuilder) : IStandardHedgingHandlerBuilder;

private sealed class EmptyResilienceStrategyOptions : ResilienceStrategyOptions
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ namespace Microsoft.Extensions.Http.Resilience;
/// </list>
/// </para>
/// The last three strategies are assigned to each individual endpoint. The selection of endpoint can be customized by
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectStrategyByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/> or
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectStrategyBy(IStandardHedgingHandlerBuilder, Func{IServiceProvider, Func{System.Net.Http.HttpRequestMessage, string}})"/> extensions.
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectPipelineByAuthority(IStandardHedgingHandlerBuilder, DataClassification)"/> or
/// <see cref="StandardHedgingHandlerBuilderExtensions.SelectPipelineBy(IStandardHedgingHandlerBuilder, Func{IServiceProvider, Func{System.Net.Http.HttpRequestMessage, string}})"/> extensions.
/// <para>
/// By default, the endpoint is selected by authority (scheme + host + port).
/// </para>
Expand All @@ -48,7 +48,7 @@ public class HttpStandardHedgingResilienceOptions
[ValidateObjectMembers]
public HttpTimeoutStrategyOptions TotalRequestTimeoutOptions { get; set; } = new HttpTimeoutStrategyOptions
{
Name = StandardHedgingStrategyNames.TotalRequestTimeout
Name = StandardHedgingPipelineNames.TotalRequestTimeout
};

/// <summary>
Expand All @@ -61,7 +61,7 @@ public class HttpStandardHedgingResilienceOptions
[ValidateObjectMembers]
public HttpHedgingStrategyOptions HedgingOptions { get; set; } = new HttpHedgingStrategyOptions
{
Name = StandardHedgingStrategyNames.Hedging
Name = StandardHedgingPipelineNames.Hedging
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.Extensions.Http.Resilience.Internal.Validators;

internal static class StandardHedgingStrategyNames
internal static class StandardHedgingPipelineNames
{
public const string CircuitBreaker = "StandardHedging-CircuitBreaker";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public ValidateOptionsResult Validate(string? name, HttpStandardHedgingResilienc
}

// if generator is specified we cannot calculate the max hedging delay
if (options.HedgingOptions.HedgingDelayGenerator == null)
if (options.HedgingOptions.DelayGenerator == null)
{
var maxHedgingDelay = TimeSpan.FromMilliseconds((options.HedgingOptions.MaxHedgedAttempts - 1) * options.HedgingOptions.HedgingDelay.TotalMilliseconds);
var maxHedgingDelay = TimeSpan.FromMilliseconds(options.HedgingOptions.MaxHedgedAttempts * options.HedgingOptions.Delay.TotalMilliseconds);

// Stryker disable once Equality
if (maxHedgingDelay > options.TotalRequestTimeoutOptions.Timeout)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ namespace Microsoft.Extensions.Http.Resilience;
public static class StandardHedgingHandlerBuilderExtensions
{
/// <summary>
/// Configures the <see cref="HttpStandardHedgingResilienceOptions"/> for the standard hedging strategy.
/// Configures the <see cref="HttpStandardHedgingResilienceOptions"/> for the standard hedging pipeline.
/// </summary>
/// <param name="builder">The strategy builder.</param>
/// <param name="builder">The pipeline builder.</param>
/// <param name="section">The section that the options will bind against.</param>
/// <returns>The same builder instance.</returns>
[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(HttpStandardHedgingResilienceOptions))]
Expand All @@ -43,9 +43,9 @@ public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHand
}

/// <summary>
/// Configures the <see cref="HttpStandardResilienceOptions"/> for the standard hedging strategy.
/// Configures the <see cref="HttpStandardResilienceOptions"/> for the standard hedging pipeline.
/// </summary>
/// <param name="builder">The strategy builder.</param>
/// <param name="builder">The pipeline builder.</param>
/// <param name="configure">The configure method.</param>
/// <returns>The same builder instance.</returns>
public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHandlerBuilder builder, Action<HttpStandardHedgingResilienceOptions> configure)
Expand All @@ -57,9 +57,9 @@ public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHand
}

/// <summary>
/// Configures the <see cref="HttpStandardResilienceOptions"/> for the standard hedging strategy.
/// Configures the <see cref="HttpStandardResilienceOptions"/> for the standard hedging pipeline.
/// </summary>
/// <param name="builder">The strategy builder.</param>
/// <param name="builder">The pipeline builder.</param>
/// <param name="configure">The configure method.</param>
/// <returns>The same builder instance.</returns>
[Experimental(diagnosticId: Experiments.Resilience, UrlFormat = Experiments.UrlFormat)]
Expand All @@ -74,38 +74,38 @@ public static IStandardHedgingHandlerBuilder Configure(this IStandardHedgingHand
}

/// <summary>
/// Instructs the underlying strategy builder to select the strategy instance by redacted authority (scheme + host + port).
/// Instructs the underlying pipeline builder to select the pipeline instance by redacted authority (scheme + host + port).
/// </summary>
/// <param name="builder">The builder instance.</param>
/// <param name="classification">The data class associated with the authority.</param>
/// <returns>The same builder instance.</returns>
/// <remarks>The authority is redacted using <see cref="Redactor"/> retrieved for <paramref name="classification"/>.</remarks>
public static IStandardHedgingHandlerBuilder SelectStrategyByAuthority(this IStandardHedgingHandlerBuilder builder, DataClassification classification)
public static IStandardHedgingHandlerBuilder SelectPipelineByAuthority(this IStandardHedgingHandlerBuilder builder, DataClassification classification)
{
_ = Throw.IfNull(builder);

var strategyName = StrategyNameHelper.GetName(builder.Name, HttpClientBuilderExtensions.StandardInnerHandlerPostfix);
var pipelineName = PipelineNameHelper.GetName(builder.Name, HttpClientBuilderExtensions.StandardInnerHandlerPostfix);

StrategyKeyProviderHelper.SelectStrategyByAuthority(builder.Services, strategyName, classification);
PipelineKeyProviderHelper.SelectPipelineByAuthority(builder.Services, pipelineName, classification);

return builder;
}

/// <summary>
/// Instructs the underlying strategy builder to select the strategy instance by custom selector.
/// Instructs the underlying pipeline builder to select the pipeline instance by custom selector.
/// </summary>
/// <param name="builder">The builder instance.</param>
/// <param name="selectorFactory">The factory that returns key selector.</param>
/// <returns>The same builder instance.</returns>
/// <remarks>The strategy key is used in metrics and logs, do not return any sensitive value.</remarks>
public static IStandardHedgingHandlerBuilder SelectStrategyBy(this IStandardHedgingHandlerBuilder builder, Func<IServiceProvider, Func<HttpRequestMessage, string>> selectorFactory)
/// <remarks>The pipeline key is used in metrics and logs, do not return any sensitive value.</remarks>
public static IStandardHedgingHandlerBuilder SelectPipelineBy(this IStandardHedgingHandlerBuilder builder, Func<IServiceProvider, Func<HttpRequestMessage, string>> selectorFactory)
{
_ = Throw.IfNull(builder);
_ = Throw.IfNull(selectorFactory);

var strategyName = StrategyNameHelper.GetName(builder.Name, HttpClientBuilderExtensions.StandardInnerHandlerPostfix);
var pipelineName = PipelineNameHelper.GetName(builder.Name, HttpClientBuilderExtensions.StandardInnerHandlerPostfix);

StrategyKeyProviderHelper.SelectStrategyBy(builder.Services, strategyName, selectorFactory);
PipelineKeyProviderHelper.SelectPipelineBy(builder.Services, pipelineName, selectorFactory);

return builder;
}
Expand Down
Loading