From 4575337f7a18a65420facf8408e423b74f7b9256 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Mon, 22 Jan 2024 14:46:57 +0100 Subject: [PATCH 01/10] [Docs] Add general usage section to chaos strategies --- docs/chaos/index.md | 31 ++++++++++++++++++++++++ src/Snippets/Docs/Chaos.Index.cs | 41 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/Snippets/Docs/Chaos.Index.cs diff --git a/docs/chaos/index.md b/docs/chaos/index.md index aa508e7351..4fff6fd4f6 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -7,6 +7,37 @@ ![Simmy](../media/simmy-logo.png) +## Usage + + +```cs +var builder = new ResiliencePipelineBuilder(); + +// First, configure regular resilience strategies +builder + .AddConcurrencyLimiter(10, 100) + .AddRetry(new()) + .AddCircuitBreaker(new()) + .AddTimeout(TimeSpan.FromSeconds(5)); + +// Finally, configure chaos strategies if you want to inject chaos. +// These should come after the regular resilience strategies. + +// 2% of invocations will be injected with chaos +const double InjectionRate = 0.02; + +builder + // Inject a chaos latency to executions + .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) + // Inject a chaos fault to executions + .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) + // Inject a chaos outcome to executions + .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) + // Inject a chaos behavior to executions + .AddChaosBehavior(0.001, () => RestartRedisAsync()); +``` + + ## Motivation There are a lot of questions when it comes to chaos engineering and making sure that a system is actually ready to face the worst possible scenarios: diff --git a/src/Snippets/Docs/Chaos.Index.cs b/src/Snippets/Docs/Chaos.Index.cs new file mode 100644 index 0000000000..da17d69105 --- /dev/null +++ b/src/Snippets/Docs/Chaos.Index.cs @@ -0,0 +1,41 @@ +using System.Net.Http; +using Polly.Simmy; + +namespace Snippets.Docs; + +internal static partial class Chaos +{ + public static void Usage() + { + #region chaos-usage + + var builder = new ResiliencePipelineBuilder(); + + // First, configure regular resilience strategies + builder + .AddConcurrencyLimiter(10, 100) + .AddRetry(new()) + .AddCircuitBreaker(new()) + .AddTimeout(TimeSpan.FromSeconds(5)); + + // Finally, configure chaos strategies if you want to inject chaos. + // These should come after the regular resilience strategies. + + // 2% of invocations will be injected with chaos + const double InjectionRate = 0.02; + + builder + // Inject a chaos latency to executions + .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) + // Inject a chaos fault to executions + .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) + // Inject a chaos outcome to executions + .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) + // Inject a chaos behavior to executions + .AddChaosBehavior(0.001, () => RestartRedisAsync()); + + #endregion + } + + private static ValueTask RestartRedisAsync() => ValueTask.CompletedTask; +} From ebb0c2ffcdd7aa9c7999e84c040fdb4063c08320 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Mon, 22 Jan 2024 14:51:39 +0100 Subject: [PATCH 02/10] fixes --- docs/chaos/index.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index 4fff6fd4f6..674cb88ee9 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -38,6 +38,9 @@ builder ``` +> [!NOTE] +> It is usual to place the chaos strategy as the last strategy in the resilience pipeline. By placing the chaos strategies as last, they subvert the usual outbound call at the last minute, substituting their fault or adding extra latency, etc. The existing resilience strategies - further out in the `ResiliencePipeline` - still apply, so you can test how the Polly resilience strategies you have configured handle the chaos/faults injected by Simmy. + ## Motivation There are a lot of questions when it comes to chaos engineering and making sure that a system is actually ready to face the worst possible scenarios: @@ -69,10 +72,6 @@ Chaos strategies (or Monkey strategies as we call them) are in essence a [Resili | [Latency](latency.md) | No | Injects latency into executions before the calls are made. | | [Behavior](behavior.md) | No | Allows you to inject *any* extra behaviour, before a call is placed. | -## Usage - -It is usual to place the chaos strategy as the last strategy in the resilience pipeline. By placing the chaos strategies as last, they subvert the usual outbound call at the last minute, substituting their fault or adding extra latency, etc. The existing resilience strategies - further out in the `ResiliencePipeline` - still apply, so you can test how the Polly resilience strategies you have configured handle the chaos/faults injected by Simmy. - ## Common options across strategies All the strategies' options implement the [`MonkeyStrategyOptions`](xref:Polly.Simmy.MonkeyStrategyOptions) class as it contains the basic configuration for every chaos strategy. From c4de7f4817d8d98a883fd008c77b2def397bddbb Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Mon, 22 Jan 2024 15:02:38 +0100 Subject: [PATCH 03/10] PR comments --- docs/chaos/index.md | 4 ++-- src/Snippets/Docs/Chaos.Index.cs | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index 674cb88ee9..9f1656a712 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -16,8 +16,8 @@ var builder = new ResiliencePipelineBuilder(); // First, configure regular resilience strategies builder .AddConcurrencyLimiter(10, 100) - .AddRetry(new()) - .AddCircuitBreaker(new()) + .AddRetry(new RetryStrategyOptions { /* configure options */ }) + .AddCircuitBreaker(new CircuitBreakerStrategyOptions { /* configure options */ }) .AddTimeout(TimeSpan.FromSeconds(5)); // Finally, configure chaos strategies if you want to inject chaos. diff --git a/src/Snippets/Docs/Chaos.Index.cs b/src/Snippets/Docs/Chaos.Index.cs index da17d69105..7c4cae8a7e 100644 --- a/src/Snippets/Docs/Chaos.Index.cs +++ b/src/Snippets/Docs/Chaos.Index.cs @@ -1,4 +1,6 @@ using System.Net.Http; +using Polly.CircuitBreaker; +using Polly.Retry; using Polly.Simmy; namespace Snippets.Docs; @@ -14,8 +16,8 @@ public static void Usage() // First, configure regular resilience strategies builder .AddConcurrencyLimiter(10, 100) - .AddRetry(new()) - .AddCircuitBreaker(new()) + .AddRetry(new RetryStrategyOptions { /* configure options */ }) + .AddCircuitBreaker(new CircuitBreakerStrategyOptions { /* configure options */ }) .AddTimeout(TimeSpan.FromSeconds(5)); // Finally, configure chaos strategies if you want to inject chaos. From 0c9161488e733b056f3aba555a0603f75e99759a Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Mon, 22 Jan 2024 15:26:01 +0100 Subject: [PATCH 04/10] Fix formatting --- docs/chaos/index.md | 12 ++++-------- src/Snippets/Docs/Chaos.Index.cs | 12 ++++-------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index 9f1656a712..c471f5b89b 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -27,14 +27,10 @@ builder const double InjectionRate = 0.02; builder - // Inject a chaos latency to executions - .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) - // Inject a chaos fault to executions - .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) - // Inject a chaos outcome to executions - .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) - // Inject a chaos behavior to executions - .AddChaosBehavior(0.001, () => RestartRedisAsync()); + .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions + .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions + .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions + .AddChaosBehavior(0.001, () => RestartRedisAsync()); // Inject a chaos behavior to executions ``` diff --git a/src/Snippets/Docs/Chaos.Index.cs b/src/Snippets/Docs/Chaos.Index.cs index 7c4cae8a7e..1304fbb7fc 100644 --- a/src/Snippets/Docs/Chaos.Index.cs +++ b/src/Snippets/Docs/Chaos.Index.cs @@ -27,14 +27,10 @@ public static void Usage() const double InjectionRate = 0.02; builder - // Inject a chaos latency to executions - .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) - // Inject a chaos fault to executions - .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) - // Inject a chaos outcome to executions - .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) - // Inject a chaos behavior to executions - .AddChaosBehavior(0.001, () => RestartRedisAsync()); + .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions + .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions + .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions + .AddChaosBehavior(0.001, () => RestartRedisAsync()); // Inject a chaos behavior to executions #endregion } From a2945bd7aacec19332383fa23fc9c7972ae26296 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Mon, 22 Jan 2024 21:07:34 +0100 Subject: [PATCH 05/10] Add missing cancellation token to behavior --- docs/chaos/behavior.md | 6 +++--- docs/chaos/index.md | 2 +- src/Polly.Core/PublicAPI.Unshipped.txt | 2 +- .../Simmy/Behavior/BehaviorPipelineBuilderExtensions.cs | 4 ++-- src/Snippets/Docs/Chaos.Behavior.cs | 8 ++++---- src/Snippets/Docs/Chaos.Index.cs | 4 ++-- .../BehaviorChaosPipelineBuilderExtensionsTests.cs | 8 ++++---- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/chaos/behavior.md b/docs/chaos/behavior.md index 44d07e8dd9..7eda8a0702 100644 --- a/docs/chaos/behavior.md +++ b/docs/chaos/behavior.md @@ -20,7 +20,7 @@ The behavior chaos strategy is designed to inject custom behaviors into system o // To use a custom delegated for injected behavior var optionsWithBehaviorGenerator = new BehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }; @@ -28,7 +28,7 @@ var optionsWithBehaviorGenerator = new BehaviorStrategyOptions // To get notifications when a behavior is injected var optionsOnBehaviorInjected = new BehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05, OnBehaviorInjected = static args => @@ -62,7 +62,7 @@ var pipeline = new ResiliencePipelineBuilder() }) .AddChaosBehavior(new BehaviorStrategyOptions // Chaos strategies are usually placed as the last ones in the pipeline { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index c471f5b89b..ce4e2db74c 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -30,7 +30,7 @@ builder .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions - .AddChaosBehavior(0.001, () => RestartRedisAsync()); // Inject a chaos behavior to executions + .AddChaosBehavior(0.001, cancellationToken => RestartRedisAsync(cancellationToken)); // Inject a chaos behavior to executions ``` diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt index af7eab4a0e..ee84a368dd 100644 --- a/src/Polly.Core/PublicAPI.Unshipped.txt +++ b/src/Polly.Core/PublicAPI.Unshipped.txt @@ -106,7 +106,7 @@ Polly.Simmy.Outcomes.OutcomeStrategyOptions.OnOutcomeInjected.set -> vo Polly.Simmy.Outcomes.OutcomeStrategyOptions.OutcomeGenerator.get -> System.Func?>>! Polly.Simmy.Outcomes.OutcomeStrategyOptions.OutcomeGenerator.set -> void Polly.Simmy.Outcomes.OutcomeStrategyOptions.OutcomeStrategyOptions() -> void -static Polly.Simmy.BehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, double injectionRate, System.Func! behavior) -> TBuilder! +static Polly.Simmy.BehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, double injectionRate, System.Func! behavior) -> TBuilder! static Polly.Simmy.BehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, Polly.Simmy.Behavior.BehaviorStrategyOptions! options) -> TBuilder! static Polly.Simmy.Fault.FaultGenerator.implicit operator System.Func>!(Polly.Simmy.Fault.FaultGenerator! generator) -> System.Func>! static Polly.Simmy.FaultPipelineBuilderExtensions.AddChaosFault(this TBuilder! builder, double injectionRate, System.Func! faultGenerator) -> TBuilder! diff --git a/src/Polly.Core/Simmy/Behavior/BehaviorPipelineBuilderExtensions.cs b/src/Polly.Core/Simmy/Behavior/BehaviorPipelineBuilderExtensions.cs index 3985819874..347b81f402 100644 --- a/src/Polly.Core/Simmy/Behavior/BehaviorPipelineBuilderExtensions.cs +++ b/src/Polly.Core/Simmy/Behavior/BehaviorPipelineBuilderExtensions.cs @@ -19,7 +19,7 @@ public static class BehaviorPipelineBuilderExtensions /// The same builder instance. /// Thrown when is . /// Thrown when the options produced from the arguments are invalid. - public static TBuilder AddChaosBehavior(this TBuilder builder, double injectionRate, Func behavior) + public static TBuilder AddChaosBehavior(this TBuilder builder, double injectionRate, Func behavior) where TBuilder : ResiliencePipelineBuilderBase { Guard.NotNull(builder); @@ -28,7 +28,7 @@ public static TBuilder AddChaosBehavior(this TBuilder builder, double { Enabled = true, InjectionRate = injectionRate, - BehaviorAction = (_) => behavior() + BehaviorAction = args => behavior(args.Context.CancellationToken) }); } diff --git a/src/Snippets/Docs/Chaos.Behavior.cs b/src/Snippets/Docs/Chaos.Behavior.cs index 16d729c57b..8d48114977 100644 --- a/src/Snippets/Docs/Chaos.Behavior.cs +++ b/src/Snippets/Docs/Chaos.Behavior.cs @@ -9,13 +9,13 @@ internal static partial class Chaos { public static void BehaviorUsage() { - static ValueTask RestartRedisVM() => ValueTask.CompletedTask; + static ValueTask RestartRedisVM(CancellationToken cancellationToken) => ValueTask.CompletedTask; #region chaos-behavior-usage // To use a custom delegated for injected behavior var optionsWithBehaviorGenerator = new BehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }; @@ -23,7 +23,7 @@ public static void BehaviorUsage() // To get notifications when a behavior is injected var optionsOnBehaviorInjected = new BehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05, OnBehaviorInjected = static args => @@ -53,7 +53,7 @@ public static void BehaviorUsage() }) .AddChaosBehavior(new BehaviorStrategyOptions // Chaos strategies are usually placed as the last ones in the pipeline { - BehaviorAction = static args => RestartRedisVM(), + BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }) diff --git a/src/Snippets/Docs/Chaos.Index.cs b/src/Snippets/Docs/Chaos.Index.cs index 1304fbb7fc..fe38f742a7 100644 --- a/src/Snippets/Docs/Chaos.Index.cs +++ b/src/Snippets/Docs/Chaos.Index.cs @@ -30,10 +30,10 @@ public static void Usage() .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions - .AddChaosBehavior(0.001, () => RestartRedisAsync()); // Inject a chaos behavior to executions + .AddChaosBehavior(0.001, cancellationToken => RestartRedisAsync(cancellationToken)); // Inject a chaos behavior to executions #endregion } - private static ValueTask RestartRedisAsync() => ValueTask.CompletedTask; + private static ValueTask RestartRedisAsync(CancellationToken cancellationToken) => ValueTask.CompletedTask; } diff --git a/test/Polly.Core.Tests/Simmy/Behavior/BehaviorChaosPipelineBuilderExtensionsTests.cs b/test/Polly.Core.Tests/Simmy/Behavior/BehaviorChaosPipelineBuilderExtensionsTests.cs index 4e41dbec53..466cfec4ce 100644 --- a/test/Polly.Core.Tests/Simmy/Behavior/BehaviorChaosPipelineBuilderExtensionsTests.cs +++ b/test/Polly.Core.Tests/Simmy/Behavior/BehaviorChaosPipelineBuilderExtensionsTests.cs @@ -10,7 +10,7 @@ public class BehaviorChaosPipelineBuilderExtensionsTests public static IEnumerable AddBehavior_Ok_Data() { var context = ResilienceContextPool.Shared.Get(); - Func behavior = () => new ValueTask(Task.CompletedTask); + Func behavior = _ => default; yield return new object[] { (ResiliencePipelineBuilder builder) => { builder.AddChaosBehavior(0.5, behavior); }, @@ -26,7 +26,7 @@ public static IEnumerable AddBehavior_Ok_Data() [Fact] public void AddBehavior_Shortcut_Option_Ok() { - var sut = new ResiliencePipelineBuilder().AddChaosBehavior(0.5, () => new ValueTask(Task.CompletedTask)).Build(); + var sut = new ResiliencePipelineBuilder().AddChaosBehavior(0.5, _ => default).Build(); sut.GetPipelineDescriptor().FirstStrategy.StrategyInstance.Should().BeOfType(); } @@ -34,7 +34,7 @@ public void AddBehavior_Shortcut_Option_Ok() public void AddBehavior_Shortcut_Option_Throws() { new ResiliencePipelineBuilder() - .Invoking(b => b.AddChaosBehavior(-1, () => new ValueTask(Task.CompletedTask))) + .Invoking(b => b.AddChaosBehavior(-1, _ => default)) .Should() .Throw(); } @@ -56,7 +56,7 @@ public void AddBehavior_Options_Ok() { Enabled = true, InjectionRate = 1, - BehaviorAction = (_) => new ValueTask(Task.CompletedTask) + BehaviorAction = (_) => default }) .Build(); From c904004de4c07a36c41a9aadbc5ab16de67835ed Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 23 Jan 2024 08:37:10 +0100 Subject: [PATCH 06/10] Cleanup --- docs/chaos/index.md | 2 +- docs/toc.yml | 4 ++-- src/Polly.Core/PublicAPI.Unshipped.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index d25c1b8c08..3d0970ce8e 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -64,7 +64,7 @@ Chaos strategies (formerly known as Monkey strategies) are in essence a [Resilie | Strategy | Reactive | What does the strategy do? | |-------------------------|----------|----------------------------------------------------------------------| | [Fault](fault.md) | No | Injects exceptions in your system. | -| [Result](result.md) | Yes | Substitute results to fake outcomes in your system. | +| [Outcome](outcome.md) | Yes | Injects fake outcomes (results or exceptions) in your system. | | [Latency](latency.md) | No | Injects latency into executions before the calls are made. | | [Behavior](behavior.md) | No | Allows you to inject *any* extra behaviour, before a call is placed. | diff --git a/docs/toc.yml b/docs/toc.yml index b4ea0b5ac1..6f0f230254 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -37,8 +37,8 @@ items: - name: Fault href: chaos/fault.md - - name: Result - href: chaos/result.md + - name: Outcome + href: chaos/outcome.md - name: Latency href: chaos/latency.md - name: Behavior diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt index a4bdba5e66..258ea4bdf2 100644 --- a/src/Polly.Core/PublicAPI.Unshipped.txt +++ b/src/Polly.Core/PublicAPI.Unshipped.txt @@ -106,7 +106,7 @@ Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions.OnOutcomeInjected.set Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions.OutcomeGenerator.get -> System.Func?>>! Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions.OutcomeGenerator.set -> void Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions.ChaosOutcomeStrategyOptions() -> void -static Polly.Simmy.ChaosBehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, double injectionRate, System.Func! behavior) -> TBuilder! +static Polly.Simmy.ChaosBehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, double injectionRate, System.Func! behavior) -> TBuilder! static Polly.Simmy.ChaosBehaviorPipelineBuilderExtensions.AddChaosBehavior(this TBuilder! builder, Polly.Simmy.Behavior.ChaosBehaviorStrategyOptions! options) -> TBuilder! static Polly.Simmy.Fault.FaultGenerator.implicit operator System.Func>!(Polly.Simmy.Fault.FaultGenerator! generator) -> System.Func>! static Polly.Simmy.ChaosFaultPipelineBuilderExtensions.AddChaosFault(this TBuilder! builder, double injectionRate, System.Func! faultGenerator) -> TBuilder! From 9ac38674c99c9d31dd93a79ac0877371cc324046 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 23 Jan 2024 08:42:48 +0100 Subject: [PATCH 07/10] fixes --- docs/chaos/index.md | 2 +- src/Snippets/Docs/Chaos.Index.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/chaos/index.md b/docs/chaos/index.md index 3d0970ce8e..0d7d4d471d 100644 --- a/docs/chaos/index.md +++ b/docs/chaos/index.md @@ -29,7 +29,7 @@ const double InjectionRate = 0.02; builder .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions - .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions + .AddChaosOutcome(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions .AddChaosBehavior(0.001, cancellationToken => RestartRedisAsync(cancellationToken)); // Inject a chaos behavior to executions ``` diff --git a/src/Snippets/Docs/Chaos.Index.cs b/src/Snippets/Docs/Chaos.Index.cs index fe38f742a7..98e40ecb91 100644 --- a/src/Snippets/Docs/Chaos.Index.cs +++ b/src/Snippets/Docs/Chaos.Index.cs @@ -29,7 +29,7 @@ public static void Usage() builder .AddChaosLatency(InjectionRate, TimeSpan.FromMinutes(1)) // Inject a chaos latency to executions .AddChaosFault(InjectionRate, () => new InvalidOperationException("Injected by chaos strategy!")) // Inject a chaos fault to executions - .AddChaosResult(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions + .AddChaosOutcome(InjectionRate, () => new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError)) // Inject a chaos outcome to executions .AddChaosBehavior(0.001, cancellationToken => RestartRedisAsync(cancellationToken)); // Inject a chaos behavior to executions #endregion From cad88e0aeadcc36b5a04fbc0808bf8c400570b79 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 23 Jan 2024 08:47:31 +0100 Subject: [PATCH 08/10] cleanup --- docs/chaos/outcome.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/chaos/outcome.md b/docs/chaos/outcome.md index 87d2c354cc..3203ef9228 100644 --- a/docs/chaos/outcome.md +++ b/docs/chaos/outcome.md @@ -6,7 +6,6 @@ ## About - **Options**: - - [`ChaosOutcomeStrategyOptions`](xref:Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions) - [`ChaosOutcomeStrategyOptions`](xref:Polly.Simmy.Outcomes.ChaosOutcomeStrategyOptions`1) - **Extensions**: `AddChaosOutcome` - **Strategy Type**: Reactive From 804e928d5e9ddbe996fbea2b41eabd153d0b11a5 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 23 Jan 2024 08:52:57 +0100 Subject: [PATCH 09/10] Drop redundant ChaosStrategyOptions --- src/Polly.Core/PublicAPI.Unshipped.txt | 22 ++++---- .../Simmy/ChaosStrategyOptions.TResult.cs | 54 ------------------- src/Polly.Core/Simmy/ChaosStrategyOptions.cs | 50 +++++++++++++++-- .../Simmy/EnabledGeneratorArguments.cs | 2 +- .../Simmy/InjectionRateGeneratorArguments.cs | 2 +- 5 files changed, 58 insertions(+), 72 deletions(-) delete mode 100644 src/Polly.Core/Simmy/ChaosStrategyOptions.TResult.cs diff --git a/src/Polly.Core/PublicAPI.Unshipped.txt b/src/Polly.Core/PublicAPI.Unshipped.txt index 258ea4bdf2..9496b0ddba 100644 --- a/src/Polly.Core/PublicAPI.Unshipped.txt +++ b/src/Polly.Core/PublicAPI.Unshipped.txt @@ -16,6 +16,16 @@ Polly.Simmy.Behavior.OnBehaviorInjectedArguments.Context.get -> Polly.Resilience Polly.Simmy.Behavior.OnBehaviorInjectedArguments.OnBehaviorInjectedArguments() -> void Polly.Simmy.Behavior.OnBehaviorInjectedArguments.OnBehaviorInjectedArguments(Polly.ResilienceContext! context) -> void Polly.Simmy.ChaosBehaviorPipelineBuilderExtensions +Polly.Simmy.ChaosStrategyOptions.Enabled.get -> bool +Polly.Simmy.ChaosStrategyOptions.Enabled.set -> void +Polly.Simmy.ChaosStrategyOptions.EnabledGenerator.get -> System.Func>? +Polly.Simmy.ChaosStrategyOptions.EnabledGenerator.set -> void +Polly.Simmy.ChaosStrategyOptions.InjectionRate.get -> double +Polly.Simmy.ChaosStrategyOptions.InjectionRate.set -> void +Polly.Simmy.ChaosStrategyOptions.InjectionRateGenerator.get -> System.Func>? +Polly.Simmy.ChaosStrategyOptions.InjectionRateGenerator.set -> void +Polly.Simmy.ChaosStrategyOptions.Randomizer.get -> System.Func! +Polly.Simmy.ChaosStrategyOptions.Randomizer.set -> void Polly.Simmy.EnabledGeneratorArguments Polly.Simmy.EnabledGeneratorArguments.Context.get -> Polly.ResilienceContext! Polly.Simmy.EnabledGeneratorArguments.EnabledGeneratorArguments() -> void @@ -71,18 +81,6 @@ Polly.Simmy.ChaosStrategy.ChaosStrategy(Polly.Simmy.ChaosStrategyOptions! opt Polly.Simmy.ChaosStrategy.ShouldInjectAsync(Polly.ResilienceContext! context) -> System.Threading.Tasks.ValueTask Polly.Simmy.ChaosStrategyOptions Polly.Simmy.ChaosStrategyOptions.ChaosStrategyOptions() -> void -Polly.Simmy.ChaosStrategyOptions -Polly.Simmy.ChaosStrategyOptions.Enabled.get -> bool -Polly.Simmy.ChaosStrategyOptions.Enabled.set -> void -Polly.Simmy.ChaosStrategyOptions.EnabledGenerator.get -> System.Func>? -Polly.Simmy.ChaosStrategyOptions.EnabledGenerator.set -> void -Polly.Simmy.ChaosStrategyOptions.InjectionRate.get -> double -Polly.Simmy.ChaosStrategyOptions.InjectionRate.set -> void -Polly.Simmy.ChaosStrategyOptions.InjectionRateGenerator.get -> System.Func>? -Polly.Simmy.ChaosStrategyOptions.InjectionRateGenerator.set -> void -Polly.Simmy.ChaosStrategyOptions.ChaosStrategyOptions() -> void -Polly.Simmy.ChaosStrategyOptions.Randomizer.get -> System.Func! -Polly.Simmy.ChaosStrategyOptions.Randomizer.set -> void Polly.Simmy.ChaosOutcomePipelineBuilderExtensions Polly.Simmy.Outcomes.OnOutcomeInjectedArguments Polly.Simmy.Outcomes.OnOutcomeInjectedArguments.Context.get -> Polly.ResilienceContext! diff --git a/src/Polly.Core/Simmy/ChaosStrategyOptions.TResult.cs b/src/Polly.Core/Simmy/ChaosStrategyOptions.TResult.cs deleted file mode 100644 index 1cf4c5a63a..0000000000 --- a/src/Polly.Core/Simmy/ChaosStrategyOptions.TResult.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Polly.Simmy; - -/// -/// The options associated with the . -/// -/// The type of result the chaos strategy handles. -public abstract class ChaosStrategyOptions : ResilienceStrategyOptions -{ - /// - /// Gets or sets the injection rate for a given execution, which the value should be between [0, 1] (inclusive). - /// - /// - /// Defaults to 0.001, meaning one in a thousand executions/0.1%. Either or this property is required. - /// - [Range(ChaosStrategyConstants.MinInjectionThreshold, ChaosStrategyConstants.MaxInjectionThreshold)] - public double InjectionRate { get; set; } = ChaosStrategyConstants.DefaultInjectionRate; - - /// - /// Gets or sets the injection rate generator for a given execution, which the value should be between [0, 1] (inclusive). - /// - /// - /// Defaults to . Either or this property is required. - /// When this property is the is used. - /// - public Func>? InjectionRateGenerator { get; set; } - - /// - /// Gets or sets the enable generator that indicates whether or not the chaos strategy is enabled for a given execution. - /// - /// - /// Defaults to . Either or this property is required. - /// When this property is the is used. - /// - public Func>? EnabledGenerator { get; set; } - - /// - /// Gets or sets a value indicating whether or not the chaos strategy is enabled for a given execution. - /// - /// - /// Defaults to . Either or this property is required. - /// - public bool Enabled { get; set; } - - /// - /// Gets or sets the Randomizer generator instance that is used to evaluate the injection rate. - /// - /// - /// The default randomizer is thread safe and returns values between 0.0 and 1.0. - /// - [Required] - public Func Randomizer { get; set; } = RandomUtil.Instance.NextDouble; -} diff --git a/src/Polly.Core/Simmy/ChaosStrategyOptions.cs b/src/Polly.Core/Simmy/ChaosStrategyOptions.cs index 34e3c0a082..3ceb4008f5 100644 --- a/src/Polly.Core/Simmy/ChaosStrategyOptions.cs +++ b/src/Polly.Core/Simmy/ChaosStrategyOptions.cs @@ -1,11 +1,53 @@ -namespace Polly.Simmy; +using System.ComponentModel.DataAnnotations; -#pragma warning disable CS8618 // Required members are not initialized in constructor since this is a DTO, default value is null +namespace Polly.Simmy; /// /// The options associated with the . /// -public abstract class ChaosStrategyOptions : ChaosStrategyOptions +public abstract class ChaosStrategyOptions : ResilienceStrategyOptions { -} + /// + /// Gets or sets the injection rate for a given execution, which the value should be between [0, 1] (inclusive). + /// + /// + /// Defaults to 0.001, meaning one in a thousand executions/0.1%. Either or this property is required. + /// + [Range(ChaosStrategyConstants.MinInjectionThreshold, ChaosStrategyConstants.MaxInjectionThreshold)] + public double InjectionRate { get; set; } = ChaosStrategyConstants.DefaultInjectionRate; + + /// + /// Gets or sets the injection rate generator for a given execution, which the value should be between [0, 1] (inclusive). + /// + /// + /// Defaults to . Either or this property is required. + /// When this property is the is used. + /// + public Func>? InjectionRateGenerator { get; set; } + + /// + /// Gets or sets the enable generator that indicates whether or not the chaos strategy is enabled for a given execution. + /// + /// + /// Defaults to . Either or this property is required. + /// When this property is the is used. + /// + public Func>? EnabledGenerator { get; set; } + /// + /// Gets or sets a value indicating whether or not the chaos strategy is enabled for a given execution. + /// + /// + /// Defaults to . Either or this property is required. + /// + public bool Enabled { get; set; } + + /// + /// Gets or sets the Randomizer generator instance that is used to evaluate the injection rate. + /// + /// + /// The default randomizer is thread safe and returns values between 0.0 and 1.0. + /// + [Required] + public Func Randomizer { get; set; } = RandomUtil.Instance.NextDouble; +} diff --git a/src/Polly.Core/Simmy/EnabledGeneratorArguments.cs b/src/Polly.Core/Simmy/EnabledGeneratorArguments.cs index 45b5cf2a46..f7e1fc677c 100644 --- a/src/Polly.Core/Simmy/EnabledGeneratorArguments.cs +++ b/src/Polly.Core/Simmy/EnabledGeneratorArguments.cs @@ -3,7 +3,7 @@ #pragma warning disable CA1815 // Override equals and operator equals on value types /// -/// Defines the arguments for the . +/// Defines the arguments for the . /// public readonly struct EnabledGeneratorArguments { diff --git a/src/Polly.Core/Simmy/InjectionRateGeneratorArguments.cs b/src/Polly.Core/Simmy/InjectionRateGeneratorArguments.cs index 8e86ce2dda..9ebf6fd9c2 100644 --- a/src/Polly.Core/Simmy/InjectionRateGeneratorArguments.cs +++ b/src/Polly.Core/Simmy/InjectionRateGeneratorArguments.cs @@ -3,7 +3,7 @@ #pragma warning disable CA1815 // Override equals and operator equals on value types /// -/// Defines the arguments for the . +/// Defines the arguments for the . /// public readonly struct InjectionRateGeneratorArguments { From 90d40042a9397faa456c135ae25930a44d72b9c4 Mon Sep 17 00:00:00 2001 From: Martin Tomka Date: Tue, 23 Jan 2024 09:15:46 +0100 Subject: [PATCH 10/10] PR comments --- docs/chaos/behavior.md | 8 ++++---- src/Snippets/Docs/Chaos.Behavior.cs | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/docs/chaos/behavior.md b/docs/chaos/behavior.md index afeba7b8a2..78f012a377 100644 --- a/docs/chaos/behavior.md +++ b/docs/chaos/behavior.md @@ -20,7 +20,7 @@ The behavior chaos strategy is designed to inject custom behaviors into system o // To use a custom delegated for injected behavior var optionsWithBehaviorGenerator = new ChaosBehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }; @@ -28,7 +28,7 @@ var optionsWithBehaviorGenerator = new ChaosBehaviorStrategyOptions // To get notifications when a behavior is injected var optionsOnBehaviorInjected = new ChaosBehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05, OnBehaviorInjected = static args => @@ -43,7 +43,7 @@ new ResiliencePipelineBuilder().AddChaosBehavior(optionsWithBehaviorGenerator); new ResiliencePipelineBuilder().AddChaosBehavior(optionsOnBehaviorInjected); // There are also a handy overload to inject the chaos easily -new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisVM); +new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisAsync); ``` @@ -62,7 +62,7 @@ var pipeline = new ResiliencePipelineBuilder() }) .AddChaosBehavior(new ChaosBehaviorStrategyOptions // Chaos strategies are usually placed as the last ones in the pipeline { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }) diff --git a/src/Snippets/Docs/Chaos.Behavior.cs b/src/Snippets/Docs/Chaos.Behavior.cs index da25e82c52..91088a51fc 100644 --- a/src/Snippets/Docs/Chaos.Behavior.cs +++ b/src/Snippets/Docs/Chaos.Behavior.cs @@ -9,13 +9,11 @@ internal static partial class Chaos { public static void BehaviorUsage() { - static ValueTask RestartRedisVM(CancellationToken cancellationToken) => ValueTask.CompletedTask; - #region chaos-behavior-usage // To use a custom delegated for injected behavior var optionsWithBehaviorGenerator = new ChaosBehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 }; @@ -23,7 +21,7 @@ public static void BehaviorUsage() // To get notifications when a behavior is injected var optionsOnBehaviorInjected = new ChaosBehaviorStrategyOptions { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05, OnBehaviorInjected = static args => @@ -38,7 +36,7 @@ public static void BehaviorUsage() new ResiliencePipelineBuilder().AddChaosBehavior(optionsOnBehaviorInjected); // There are also a handy overload to inject the chaos easily - new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisVM); + new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisAsync); #endregion #region chaos-behavior-execution @@ -53,7 +51,7 @@ public static void BehaviorUsage() }) .AddChaosBehavior(new ChaosBehaviorStrategyOptions // Chaos strategies are usually placed as the last ones in the pipeline { - BehaviorAction = static args => RestartRedisVM(args.Context.CancellationToken), + BehaviorAction = static args => RestartRedisAsync(args.Context.CancellationToken), Enabled = true, InjectionRate = 0.05 })