From 25512e06472dd847b5aab2ac87d98b2f49c21263 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 30 May 2023 10:07:01 +0200 Subject: [PATCH 1/5] Simplify the creation of outcome invokers --- .../CircuitBreakerResilienceStrategyTests.cs | 2 +- .../Controller/CircuitStateControllerTests.cs | 4 +-- .../GenericResilienceStrategyBuilderTests.cs | 1 + .../ResilienceStrategyBuilderTests.cs | 1 + .../Retry/RetryResilienceStrategyTests.cs | 6 ++--- .../Strategy/EventInvokerTests.cs | 14 +++++----- .../Strategy/GeneratorInvokerTests.cs | 15 ++++++----- .../Strategy/PredicateInvokerTests.cs | 14 +++++----- .../ResilienceStrategyBuilderContextTests.cs | 3 ++- ...akerResilienceStrategyBuilderExtensions.cs | 12 ++++----- .../ResilienceStrategyBuilder.TResult.cs | 11 ++++++-- src/Polly.Core/ResilienceStrategyBuilder.cs | 5 +++- ...etryResilienceStrategyBuilderExtensions.cs | 12 ++++----- src/Polly.Core/Strategy/EventInvoker.cs | 11 ++++---- src/Polly.Core/Strategy/GeneratorInvoker.cs | 14 ++++++---- src/Polly.Core/Strategy/PredicateInvoker.cs | 9 ++++--- .../ResilienceStrategyBuilderContext.cs | 27 ++++++++++++++++++- 17 files changed, 107 insertions(+), 54 deletions(-) diff --git a/src/Polly.Core.Tests/CircuitBreaker/CircuitBreakerResilienceStrategyTests.cs b/src/Polly.Core.Tests/CircuitBreaker/CircuitBreakerResilienceStrategyTests.cs index 73b11cd7c96..2aacb3ed013 100644 --- a/src/Polly.Core.Tests/CircuitBreaker/CircuitBreakerResilienceStrategyTests.cs +++ b/src/Polly.Core.Tests/CircuitBreaker/CircuitBreakerResilienceStrategyTests.cs @@ -134,6 +134,6 @@ public void Execute_Ok() private CircuitBreakerResilienceStrategy Create() { - return new(PredicateInvoker.NonGeneric(_options.ShouldHandle!), _controller, _options.StateProvider, _options.ManualControl); + return new(PredicateInvoker.Create(_options.ShouldHandle!, false)!, _controller, _options.StateProvider, _options.ManualControl); } } diff --git a/src/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs b/src/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs index 0a6f12f3d66..2ead5c3ff8e 100644 --- a/src/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs +++ b/src/Polly.Core.Tests/CircuitBreaker/Controller/CircuitStateControllerTests.cs @@ -435,8 +435,8 @@ private async Task OpenCircuit(CircuitStateController controller, Outcome? private CircuitStateController CreateController() => new( _options.BreakDuration, - EventInvoker.NonGeneric(_options.OnOpened), - EventInvoker.NonGeneric(_options.OnClosed), + EventInvoker.Create(_options.OnOpened, false), + EventInvoker.Create(_options.OnClosed, false), _options.OnHalfOpened, _circuitBehavior.Object, _timeProvider.Object, diff --git a/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs b/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs index 7599e0d8f01..c2131486743 100644 --- a/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs +++ b/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs @@ -15,6 +15,7 @@ public void Ctor_EnsureDefaults() _builder.Properties.Should().NotBeNull(); _builder.TimeProvider.Should().Be(TimeProvider.System); _builder.OnCreatingStrategy.Should().BeNull(); + _builder.Builder.IsGenericBuilder.Should().BeTrue(); } [Fact] diff --git a/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs b/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs index 8ebeb71150b..fecd2ba03fd 100644 --- a/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs +++ b/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs @@ -15,6 +15,7 @@ public void Ctor_EnsureDefaults() builder.BuilderName.Should().Be(""); builder.Properties.Should().NotBeNull(); builder.TimeProvider.Should().Be(TimeProvider.System); + builder.IsGenericBuilder.Should().BeFalse(); } [Fact] diff --git a/src/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs b/src/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs index 1d995e290d5..49a8c5a6aac 100644 --- a/src/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs +++ b/src/Polly.Core.Tests/Retry/RetryResilienceStrategyTests.cs @@ -232,9 +232,9 @@ private RetryResilienceStrategy CreateSut() _options.BaseDelay, _options.BackoffType, _options.RetryCount, - PredicateInvoker.NonGeneric(_options.ShouldRetry!), - EventInvoker.NonGeneric(_options.OnRetry), - GeneratorInvoker.NonGeneric(_options.RetryDelayGenerator), + PredicateInvoker.Create(_options.ShouldRetry!, false)!, + EventInvoker.Create(_options.OnRetry, false), + GeneratorInvoker.Create(_options.RetryDelayGenerator, TimeSpan.MinValue, false), _timeProvider.Object, _telemetry, RandomUtil.Instance); diff --git a/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs b/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs index 88a238dafc0..41f541e26c7 100644 --- a/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs @@ -9,8 +9,8 @@ public class EventInvokerTests [Fact] public void NullCallback_Ok() { - EventInvoker.NonGeneric(null).Should().BeNull(); - EventInvoker.Generic(null).Should().BeNull(); + EventInvoker.Create(null, isGeneric: true).Should().BeNull(); + EventInvoker.Create(null, isGeneric: true).Should().BeNull(); } [Fact] @@ -18,13 +18,14 @@ public async Task HandleAsync_NonGeneric_Ok() { var args = new TestArguments(ResilienceContext.Get()); var called = false; - var invoker = EventInvoker.NonGeneric((outcome, args) => + var invoker = EventInvoker.Create((outcome, args) => { outcome.Result.Should().Be(10); args.Context.Should().NotBeNull(); called = true; return default; - })!; + }, + false)!; await invoker.HandleAsync(new Outcome(10), args); called.Should().Be(true); @@ -35,13 +36,14 @@ public async Task HandleAsync_Generic_Ok() { var args = new TestArguments(ResilienceContext.Get()); var called = false; - var invoker = EventInvoker.Generic((outcome, args) => + var invoker = EventInvoker.Create((outcome, args) => { args.Context.Should().NotBeNull(); outcome.Result.Should().Be(10); called = true; return default; - })!; + }, + true)!; await invoker.HandleAsync(new Outcome(10), args); called.Should().Be(true); diff --git a/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs b/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs index fc1228f5ae0..d59a26c487b 100644 --- a/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs @@ -8,21 +8,23 @@ public class GeneratorInvokerTests [Fact] public void NullCallback_Ok() { - GeneratorInvoker.NonGeneric(null).Should().BeNull(); - GeneratorInvoker.Generic(null, "default").Should().BeNull(); + GeneratorInvoker.Create(null, "default", false).Should().BeNull(); + GeneratorInvoker.Create(null, "default", true).Should().BeNull(); } [Fact] public async Task HandleAsync_NonGeneric_Ok() { var args = new TestArguments(ResilienceContext.Get()); - var invoker = GeneratorInvoker.NonGeneric((outcome, args) => + var invoker = GeneratorInvoker.Create((outcome, args) => { args.Context.Should().NotBeNull(); outcome.Result.Should().Be(10); return new ValueTask("generated-value"); - })!; + }, + "default", + false)!; (await invoker.HandleAsync(new Outcome(10), args)).Should().Be("generated-value"); } @@ -31,14 +33,15 @@ public async Task HandleAsync_NonGeneric_Ok() public async Task HandleAsync_Generic_Ok() { var args = new TestArguments(ResilienceContext.Get()); - var invoker = GeneratorInvoker.Generic((outcome, args) => + var invoker = GeneratorInvoker.Create((outcome, args) => { args.Context.Should().NotBeNull(); outcome.Result.Should().Be(10); return new ValueTask("generated-value"); }, - "default")!; + "default", + true)!; (await invoker.HandleAsync(new Outcome(10), args)).Should().Be("generated-value"); (await invoker.HandleAsync(new Outcome("dummy"), args)).Should().Be("default"); diff --git a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs index c42e8194867..6971239857e 100644 --- a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs @@ -11,15 +11,16 @@ public async Task HandleAsync_NonGeneric_Ok() { var args = new TestArguments(ResilienceContext.Get()); var called = false; - var invoker = PredicateInvoker.NonGeneric((outcome, _) => + var invoker = PredicateInvoker.Create((outcome, _) => { outcome.Result.Should().Be(10); args.Context.Should().NotBeNull(); called = true; return new ValueTask(true); - }); + }, + false); - (await invoker.HandleAsync(new Outcome(10), args)).Should().Be(true); + (await invoker!.HandleAsync(new Outcome(10), args)).Should().Be(true); called.Should().Be(true); } @@ -28,15 +29,16 @@ public async Task HandleAsync_Generic_Ok() { var args = new TestArguments(ResilienceContext.Get()); var called = false; - var invoker = PredicateInvoker.Generic((outcome, args) => + var invoker = PredicateInvoker.Create((outcome, args) => { outcome.Result.Should().Be(10); args.Context.Should().NotBeNull(); called = true; return new ValueTask(true); - }); + }, + true); - (await invoker.HandleAsync(new Outcome(10), args)).Should().Be(true); + (await invoker!.HandleAsync(new Outcome(10), args)).Should().Be(true); called.Should().Be(true); called = false; diff --git a/src/Polly.Core.Tests/Strategy/ResilienceStrategyBuilderContextTests.cs b/src/Polly.Core.Tests/Strategy/ResilienceStrategyBuilderContextTests.cs index b8c44c9b710..2a1760c92aa 100644 --- a/src/Polly.Core.Tests/Strategy/ResilienceStrategyBuilderContextTests.cs +++ b/src/Polly.Core.Tests/Strategy/ResilienceStrategyBuilderContextTests.cs @@ -10,8 +10,9 @@ public void Ctor_EnsureDefaults() { var properties = new ResilienceProperties(); var timeProvider = new FakeTimeProvider(); - var context = new ResilienceStrategyBuilderContext("builder-name", properties, "strategy-name", "strategy-type", timeProvider.Object); + var context = new ResilienceStrategyBuilderContext("builder-name", properties, "strategy-name", "strategy-type", timeProvider.Object, true); + context.IsGenericBuilder.Should().BeTrue(); context.BuilderName.Should().Be("builder-name"); context.BuilderProperties.Should().BeSameAs(properties); context.StrategyName.Should().Be("strategy-name"); diff --git a/src/Polly.Core/CircuitBreaker/CircuitBreakerResilienceStrategyBuilderExtensions.cs b/src/Polly.Core/CircuitBreaker/CircuitBreakerResilienceStrategyBuilderExtensions.cs index 76412ce3dde..86dd41fc444 100644 --- a/src/Polly.Core/CircuitBreaker/CircuitBreakerResilienceStrategyBuilderExtensions.cs +++ b/src/Polly.Core/CircuitBreaker/CircuitBreakerResilienceStrategyBuilderExtensions.cs @@ -132,15 +132,15 @@ internal static CircuitBreakerResilienceStrategy CreateStrategy(ResilienceStrate { var controller = new CircuitStateController( options.BreakDuration, - EventInvoker.NonGeneric(options.OnOpened), - EventInvoker.NonGeneric(options.OnClosed), + context.CreateInvoker(options.OnOpened), + context.CreateInvoker(options.OnClosed), options.OnHalfOpened, behavior, context.TimeProvider, context.Telemetry); return new CircuitBreakerResilienceStrategy( - PredicateInvoker.NonGeneric(options.ShouldHandle!), + context.CreateInvoker(options.ShouldHandle)!, controller, options.StateProvider, options.ManualControl); @@ -150,15 +150,15 @@ internal static CircuitBreakerResilienceStrategy CreateStrategy(Resilie { var controller = new CircuitStateController( options.BreakDuration, - EventInvoker.Generic(options.OnOpened), - EventInvoker.Generic(options.OnClosed), + context.CreateInvoker(options.OnOpened), + context.CreateInvoker(options.OnClosed), options.OnHalfOpened, behavior, context.TimeProvider, context.Telemetry); return new CircuitBreakerResilienceStrategy( - PredicateInvoker.Generic(options.ShouldHandle!), + context.CreateInvoker(options.ShouldHandle)!, controller, options.StateProvider, options.ManualControl); diff --git a/src/Polly.Core/ResilienceStrategyBuilder.TResult.cs b/src/Polly.Core/ResilienceStrategyBuilder.TResult.cs index ba9f8fce068..f4b880a4f1f 100644 --- a/src/Polly.Core/ResilienceStrategyBuilder.TResult.cs +++ b/src/Polly.Core/ResilienceStrategyBuilder.TResult.cs @@ -17,9 +17,16 @@ public class ResilienceStrategyBuilder /// /// Initializes a new instance of the class. /// - public ResilienceStrategyBuilder() => Builder = new(); + public ResilienceStrategyBuilder() => Builder = new() + { + IsGenericBuilder = true + }; - internal ResilienceStrategyBuilder(ResilienceStrategyBuilder builder) => Builder = builder; + internal ResilienceStrategyBuilder(ResilienceStrategyBuilder builder) + { + Builder = builder; + Builder.IsGenericBuilder = true; + } /// /// Gets or sets the name of the builder. diff --git a/src/Polly.Core/ResilienceStrategyBuilder.cs b/src/Polly.Core/ResilienceStrategyBuilder.cs index c8060f1bceb..19f22decce4 100644 --- a/src/Polly.Core/ResilienceStrategyBuilder.cs +++ b/src/Polly.Core/ResilienceStrategyBuilder.cs @@ -42,6 +42,8 @@ public class ResilienceStrategyBuilder /// internal Action>? OnCreatingStrategy { get; set; } + internal bool IsGenericBuilder { get; set; } + /// /// Adds an already created strategy instance to the builder. /// @@ -116,7 +118,8 @@ private ResilienceStrategy CreateResilienceStrategy(Entry entry) builderProperties: Properties, strategyName: entry.Properties.StrategyName, strategyType: entry.Properties.StrategyType, - timeProvider: TimeProvider); + timeProvider: TimeProvider, + IsGenericBuilder); return entry.Factory(context); } diff --git a/src/Polly.Core/Retry/RetryResilienceStrategyBuilderExtensions.cs b/src/Polly.Core/Retry/RetryResilienceStrategyBuilderExtensions.cs index d7941574051..a4da4459cbb 100644 --- a/src/Polly.Core/Retry/RetryResilienceStrategyBuilderExtensions.cs +++ b/src/Polly.Core/Retry/RetryResilienceStrategyBuilderExtensions.cs @@ -143,9 +143,9 @@ public static ResilienceStrategyBuilder AddRetry(this Resilien options.BaseDelay, options.BackoffType, options.RetryCount, - PredicateInvoker.Generic(options.ShouldRetry!), - EventInvoker.Generic(options.OnRetry), - GeneratorInvoker.Generic(options.RetryDelayGenerator, TimeSpan.MinValue), + context.CreateInvoker(options.ShouldRetry)!, + context.CreateInvoker(options.OnRetry), + context.CreateInvoker(options.RetryDelayGenerator, TimeSpan.MinValue), context.TimeProvider, context.Telemetry, RandomUtil.Instance), @@ -172,9 +172,9 @@ public static ResilienceStrategyBuilder AddRetry(this ResilienceStrategyBuilder options.BaseDelay, options.BackoffType, options.RetryCount, - PredicateInvoker.NonGeneric(options.ShouldRetry!), - EventInvoker.NonGeneric(options.OnRetry), - GeneratorInvoker.NonGeneric(options.RetryDelayGenerator), + context.CreateInvoker(options.ShouldRetry)!, + context.CreateInvoker(options.OnRetry), + context.CreateInvoker(options.RetryDelayGenerator, TimeSpan.MinValue), context.TimeProvider, context.Telemetry, RandomUtil.Instance), diff --git a/src/Polly.Core/Strategy/EventInvoker.cs b/src/Polly.Core/Strategy/EventInvoker.cs index 97e9424e3fe..ee85926eeff 100644 --- a/src/Polly.Core/Strategy/EventInvoker.cs +++ b/src/Polly.Core/Strategy/EventInvoker.cs @@ -5,11 +5,12 @@ namespace Polly.Strategy; internal abstract class EventInvoker where TArgs : IResilienceArguments { - public static EventInvoker? NonGeneric(Func, TArgs, ValueTask>? callback) - => callback == null ? null : new NonGenericEventInvoker(callback); - - public static EventInvoker? Generic(Func, TArgs, ValueTask>? callback) - => callback == null ? null : new GenericEventInvoker(callback); + public static EventInvoker? Create(Func, TArgs, ValueTask>? callback, bool isGeneric) => callback switch + { + null => null, + Func, TArgs, ValueTask> generic when !isGeneric => new NonGenericEventInvoker(generic), + _ => new GenericEventInvoker(callback) + }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); diff --git a/src/Polly.Core/Strategy/GeneratorInvoker.cs b/src/Polly.Core/Strategy/GeneratorInvoker.cs index 857f6ea119a..66a52abd871 100644 --- a/src/Polly.Core/Strategy/GeneratorInvoker.cs +++ b/src/Polly.Core/Strategy/GeneratorInvoker.cs @@ -5,11 +5,15 @@ namespace Polly.Strategy; internal abstract class GeneratorInvoker where TArgs : IResilienceArguments { - public static GeneratorInvoker? NonGeneric(Func, TArgs, ValueTask>? generator) - => generator == null ? null : new NonGenericGeneratorInvoker(generator); - - public static GeneratorInvoker? Generic(Func, TArgs, ValueTask>? generator, TValue defaultValue) - => generator == null ? null : new GenericGeneratorInvoker(generator, defaultValue); + public static GeneratorInvoker? Create( + Func, TArgs, ValueTask>? generator, + TValue defaultValue, + bool isGeneric) => generator switch + { + null => null, + Func, TArgs, ValueTask> objectGenerator when !isGeneric => new NonGenericGeneratorInvoker(objectGenerator), + _ => new GenericGeneratorInvoker(generator, defaultValue) + }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); diff --git a/src/Polly.Core/Strategy/PredicateInvoker.cs b/src/Polly.Core/Strategy/PredicateInvoker.cs index 8e4ca79cc0f..d9bf6be9d26 100644 --- a/src/Polly.Core/Strategy/PredicateInvoker.cs +++ b/src/Polly.Core/Strategy/PredicateInvoker.cs @@ -5,9 +5,12 @@ namespace Polly.Strategy; internal abstract class PredicateInvoker where TArgs : IResilienceArguments { - public static PredicateInvoker NonGeneric(Func, TArgs, ValueTask> predicate) => new NonGenericPredicateInvoker(predicate); - - public static PredicateInvoker Generic(Func, TArgs, ValueTask> predicate) => new GenericPredicateInvoker(predicate); + public static PredicateInvoker? Create(Func, TArgs, ValueTask>? predicate, bool isGeneric) => predicate switch + { + null => null, + Func, TArgs, ValueTask> objectPredicate when !isGeneric => new NonGenericPredicateInvoker(objectPredicate), + _ => new GenericPredicateInvoker(predicate) + }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); diff --git a/src/Polly.Core/Strategy/ResilienceStrategyBuilderContext.cs b/src/Polly.Core/Strategy/ResilienceStrategyBuilderContext.cs index 56d45147e6e..3bee9262e2f 100644 --- a/src/Polly.Core/Strategy/ResilienceStrategyBuilderContext.cs +++ b/src/Polly.Core/Strategy/ResilienceStrategyBuilderContext.cs @@ -1,3 +1,4 @@ +using System; using Polly.Telemetry; namespace Polly.Strategy; @@ -12,13 +13,15 @@ internal ResilienceStrategyBuilderContext( ResilienceProperties builderProperties, string strategyName, string strategyType, - TimeProvider timeProvider) + TimeProvider timeProvider, + bool isGenericBuilder) { BuilderName = builderName; BuilderProperties = builderProperties; StrategyName = strategyName; StrategyType = strategyType; TimeProvider = timeProvider; + IsGenericBuilder = isGenericBuilder; Telemetry = TelemetryUtil.CreateTelemetry(builderName, builderProperties, strategyName, strategyType); } @@ -51,4 +54,26 @@ internal ResilienceStrategyBuilderContext( /// Gets the used by this strategy. /// internal TimeProvider TimeProvider { get; } + + internal bool IsGenericBuilder { get; } + + internal PredicateInvoker? CreateInvoker(Func, TArgs, ValueTask>? predicate) + where TArgs : IResilienceArguments + { + return PredicateInvoker.Create(predicate, IsGenericBuilder); + } + + internal EventInvoker? CreateInvoker(Func, TArgs, ValueTask>? callback) + where TArgs : IResilienceArguments + { + return EventInvoker.Create(callback, IsGenericBuilder); + } + + internal GeneratorInvoker? CreateInvoker( + Func, TArgs, ValueTask>? generator, + TValue defaultValue) + where TArgs : IResilienceArguments + { + return GeneratorInvoker.Create(generator, defaultValue, IsGenericBuilder); + } } From 1a12bd3a137d9e20f70c3ca2c609ee6bc4fbda5b Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 30 May 2023 10:17:57 +0200 Subject: [PATCH 2/5] fixes --- .../Fallback/FallbackResilienceStrategyTests.cs | 2 +- .../Hedging/HedgingResilienceStrategyTests.cs | 2 +- .../Fallback/FallbackResilienceStrategyBuilderExtensions.cs | 4 ++-- .../Hedging/HedgingResilienceStrategyBuilderExtensions.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Polly.Core.Tests/Fallback/FallbackResilienceStrategyTests.cs b/src/Polly.Core.Tests/Fallback/FallbackResilienceStrategyTests.cs index 6a49f4b630c..32dc9dea4ba 100644 --- a/src/Polly.Core.Tests/Fallback/FallbackResilienceStrategyTests.cs +++ b/src/Polly.Core.Tests/Fallback/FallbackResilienceStrategyTests.cs @@ -130,6 +130,6 @@ public void Handle_UnhandledResult_Ok() private FallbackResilienceStrategy Create() => new( _options.Handler.CreateHandler(), - EventInvoker.NonGeneric(_options.OnFallback), + EventInvoker.Create(_options.OnFallback, false), _telemetry); } diff --git a/src/Polly.Core.Tests/Hedging/HedgingResilienceStrategyTests.cs b/src/Polly.Core.Tests/Hedging/HedgingResilienceStrategyTests.cs index 02a5cf2b492..8082ddc8098 100644 --- a/src/Polly.Core.Tests/Hedging/HedgingResilienceStrategyTests.cs +++ b/src/Polly.Core.Tests/Hedging/HedgingResilienceStrategyTests.cs @@ -888,7 +888,7 @@ private void ConfigureHedging(TimeSpan delay) => ConfigureHedging(args => async _options.HedgingDelay, _options.MaxHedgedAttempts, _options.Handler.CreateHandler(), - EventInvoker.NonGeneric(_options.OnHedging), + EventInvoker.Create(_options.OnHedging, false), _options.HedgingDelayGenerator, _timeProvider, _telemetry); diff --git a/src/Polly.Core/Fallback/FallbackResilienceStrategyBuilderExtensions.cs b/src/Polly.Core/Fallback/FallbackResilienceStrategyBuilderExtensions.cs index 4db1287ed88..684a1643005 100644 --- a/src/Polly.Core/Fallback/FallbackResilienceStrategyBuilderExtensions.cs +++ b/src/Polly.Core/Fallback/FallbackResilienceStrategyBuilderExtensions.cs @@ -68,7 +68,7 @@ public static ResilienceStrategyBuilder AddFallback(this Resil return builder.AddStrategy(context => new FallbackResilienceStrategy( handler, - EventInvoker.Generic(options.OnFallback), + context.CreateInvoker(options.OnFallback), context.Telemetry), options); } @@ -91,7 +91,7 @@ internal static ResilienceStrategyBuilder AddFallback(this ResilienceStrategyBui return builder.AddStrategy(context => new FallbackResilienceStrategy( options.Handler.CreateHandler(), - EventInvoker.NonGeneric(options.OnFallback), + context.CreateInvoker(options.OnFallback), context.Telemetry), options); } diff --git a/src/Polly.Core/Hedging/HedgingResilienceStrategyBuilderExtensions.cs b/src/Polly.Core/Hedging/HedgingResilienceStrategyBuilderExtensions.cs index a232417fa32..2da690b410a 100644 --- a/src/Polly.Core/Hedging/HedgingResilienceStrategyBuilderExtensions.cs +++ b/src/Polly.Core/Hedging/HedgingResilienceStrategyBuilderExtensions.cs @@ -38,7 +38,7 @@ public static ResilienceStrategyBuilder AddHedging(this Resili options.HedgingDelay, options.MaxHedgedAttempts, handler, - EventInvoker.Generic(options.OnHedging), + context.CreateInvoker(options.OnHedging), options.HedgingDelayGenerator, context.TimeProvider, context.Telemetry), @@ -65,7 +65,7 @@ internal static ResilienceStrategyBuilder AddHedging(this ResilienceStrategyBuil options.HedgingDelay, options.MaxHedgedAttempts, options.Handler.CreateHandler(), - EventInvoker.NonGeneric(options.OnHedging), + context.CreateInvoker(options.OnHedging), options.HedgingDelayGenerator, context.TimeProvider, context.Telemetry), From c926da2d5da4da3803114028bd1fece613f8be7f Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 30 May 2023 10:26:49 +0200 Subject: [PATCH 3/5] fixes --- src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs | 7 +++++++ src/Polly.Core/Strategy/EventInvoker.cs | 4 ++-- src/Polly.Core/Strategy/GeneratorInvoker.cs | 4 ++-- src/Polly.Core/Strategy/PredicateInvoker.cs | 4 ++-- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs index 6971239857e..1c43d9af70e 100644 --- a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs @@ -6,6 +6,13 @@ namespace Polly.Core.Tests.Strategy; public class PredicateInvokerTests { + [Fact] + public void NullCallback_Ok() + { + PredicateInvoker.Create(null, isGeneric: true).Should().BeNull(); + PredicateInvoker.Create(null, isGeneric: true).Should().BeNull(); + } + [Fact] public async Task HandleAsync_NonGeneric_Ok() { diff --git a/src/Polly.Core/Strategy/EventInvoker.cs b/src/Polly.Core/Strategy/EventInvoker.cs index ee85926eeff..a2da6673da5 100644 --- a/src/Polly.Core/Strategy/EventInvoker.cs +++ b/src/Polly.Core/Strategy/EventInvoker.cs @@ -7,9 +7,9 @@ internal abstract class EventInvoker { public static EventInvoker? Create(Func, TArgs, ValueTask>? callback, bool isGeneric) => callback switch { - null => null, Func, TArgs, ValueTask> generic when !isGeneric => new NonGenericEventInvoker(generic), - _ => new GenericEventInvoker(callback) + { } => new GenericEventInvoker(callback), + _ => null, }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); diff --git a/src/Polly.Core/Strategy/GeneratorInvoker.cs b/src/Polly.Core/Strategy/GeneratorInvoker.cs index 66a52abd871..8a3aa4d9f47 100644 --- a/src/Polly.Core/Strategy/GeneratorInvoker.cs +++ b/src/Polly.Core/Strategy/GeneratorInvoker.cs @@ -10,9 +10,9 @@ internal abstract class GeneratorInvoker TValue defaultValue, bool isGeneric) => generator switch { - null => null, Func, TArgs, ValueTask> objectGenerator when !isGeneric => new NonGenericGeneratorInvoker(objectGenerator), - _ => new GenericGeneratorInvoker(generator, defaultValue) + { } => new GenericGeneratorInvoker(generator, defaultValue), + _ => null }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); diff --git a/src/Polly.Core/Strategy/PredicateInvoker.cs b/src/Polly.Core/Strategy/PredicateInvoker.cs index d9bf6be9d26..96be569e6ec 100644 --- a/src/Polly.Core/Strategy/PredicateInvoker.cs +++ b/src/Polly.Core/Strategy/PredicateInvoker.cs @@ -7,9 +7,9 @@ internal abstract class PredicateInvoker { public static PredicateInvoker? Create(Func, TArgs, ValueTask>? predicate, bool isGeneric) => predicate switch { - null => null, Func, TArgs, ValueTask> objectPredicate when !isGeneric => new NonGenericPredicateInvoker(objectPredicate), - _ => new GenericPredicateInvoker(predicate) + { } => new GenericPredicateInvoker(predicate), + _ => null, }; public abstract ValueTask HandleAsync(Outcome outcome, TArgs args); From ad6bbf7dcbbe30222024767478f1bacd47b0fcb3 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 30 May 2023 11:00:06 +0200 Subject: [PATCH 4/5] new tests --- src/Polly.Core.Tests/Strategy/EventInvokerTests.cs | 13 +++++++++++++ .../Strategy/GeneratorInvokerTests.cs | 13 +++++++++++++ .../Strategy/PredicateInvokerTests.cs | 9 +++++++++ 3 files changed, 35 insertions(+) diff --git a/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs b/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs index 41f541e26c7..a76e7512647 100644 --- a/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/EventInvokerTests.cs @@ -52,4 +52,17 @@ public async Task HandleAsync_Generic_Ok() await invoker.HandleAsync(new Outcome("dummy"), args); called.Should().Be(false); } + + [Fact] + public async Task HandleAsync_GenericObject_Ok() + { + var called = false; + var args = new TestArguments(ResilienceContext.Get()); + var invoker = EventInvoker.Create((_, _) => { called = true; return default; }, true); + await invoker!.HandleAsync(new Outcome("dummy"), args); + called.Should().BeFalse(); + + await invoker!.HandleAsync(new Outcome("dummy"), args); + called.Should().BeTrue(); + } } diff --git a/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs b/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs index d59a26c487b..5009ee9ff5f 100644 --- a/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/GeneratorInvokerTests.cs @@ -45,5 +45,18 @@ public async Task HandleAsync_Generic_Ok() (await invoker.HandleAsync(new Outcome(10), args)).Should().Be("generated-value"); (await invoker.HandleAsync(new Outcome("dummy"), args)).Should().Be("default"); + + invoker = GeneratorInvoker.Create((_, _) => new ValueTask("dummy"), "default", true); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().Be("default"); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().Be("dummy"); + } + + [Fact] + public async Task HandleAsync_GenericObject_Ok() + { + var args = new TestArguments(ResilienceContext.Get()); + var invoker = GeneratorInvoker.Create((_, _) => new ValueTask("dummy"), "default", true); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().Be("default"); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().Be("dummy"); } } diff --git a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs index 1c43d9af70e..1d39b7e8331 100644 --- a/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs +++ b/src/Polly.Core.Tests/Strategy/PredicateInvokerTests.cs @@ -52,4 +52,13 @@ public async Task HandleAsync_Generic_Ok() (await invoker.HandleAsync(new Outcome("dummy"), args)).Should().Be(false); called.Should().Be(false); } + + [Fact] + public async Task HandleAsync_GenericObject_Ok() + { + var args = new TestArguments(ResilienceContext.Get()); + var invoker = PredicateInvoker.Create((_, _) => PredicateResult.True, true); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().BeFalse(); + (await invoker!.HandleAsync(new Outcome("dummy"), args)).Should().BeTrue(); + } } From 68452880f2714b1c5b1fa3234618736c352790dd Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 30 May 2023 11:21:47 +0200 Subject: [PATCH 5/5] new tests --- .../GenericResilienceStrategyBuilderTests.cs | 6 ++++++ src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs b/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs index c2131486743..d171f05dc73 100644 --- a/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs +++ b/src/Polly.Core.Tests/GenericResilienceStrategyBuilderTests.cs @@ -18,6 +18,12 @@ public void Ctor_EnsureDefaults() _builder.Builder.IsGenericBuilder.Should().BeTrue(); } + [Fact] + public void CopyCtor_Ok() + { + new ResilienceStrategyBuilder(new ResilienceStrategyBuilder()).Builder.IsGenericBuilder.Should().BeTrue(); + } + [Fact] public void Properties_GetSet_Ok() { diff --git a/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs b/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs index fecd2ba03fd..c1f5a401476 100644 --- a/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs +++ b/src/Polly.Core.Tests/ResilienceStrategyBuilderTests.cs @@ -251,12 +251,14 @@ public void BuildStrategy_EnsureCorrectContext() var builder = new ResilienceStrategyBuilder { BuilderName = "builder-name", - TimeProvider = new FakeTimeProvider().Object + TimeProvider = new FakeTimeProvider().Object, + IsGenericBuilder = true }; builder.AddStrategy( context => { + context.IsGenericBuilder.Should().BeTrue(); context.BuilderName.Should().Be("builder-name"); context.StrategyName.Should().Be("strategy-name"); context.StrategyType.Should().Be("Test");