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

Simmy v8 #1459

Merged
merged 55 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9641b20
* add MonkeyStrategy as the main ChaosStrategy class which all chaos …
vany0114 Jun 25, 2023
3caf98f
Merge branch 'main' into simmy-v8
vany0114 Jun 25, 2023
fadd5b2
* add LatencyChaosStrategyBuilderExtensions: still need to add the ge…
vany0114 Jun 26, 2023
10d820b
Merge branch 'main' into simmy-v8
vany0114 Jun 26, 2023
25b15d8
* allows passing both a generator or a primitive value for injection …
vany0114 Jul 1, 2023
17fa6dc
Merge branch 'main' into simmy-v8
vany0114 Jul 1, 2023
4d98524
fixes after synching with the main branch
vany0114 Jul 1, 2023
a9329ae
fate time provider is not working, it gets hung forever
vany0114 Jul 2, 2023
bb47bfa
Merge branch 'main' into simmy-v8
vany0114 Jul 2, 2023
af7e4cf
add behavior chaos strategy
vany0114 Jul 2, 2023
17d1bb4
OutComeChaosStrategy implemenation: WIP
vany0114 Jul 2, 2023
b03d4cb
improves MonkeyStrategy generic implementation so that it encapsulate…
vany0114 Jul 3, 2023
09fb163
fix docs
vany0114 Jul 3, 2023
090159d
abstract ConvertValueTask functionality
vany0114 Jul 3, 2023
1dc047c
Merge branch 'main' into simmy-v8
vany0114 Jul 3, 2023
0dcf121
add outcomes buileder extensions
vany0114 Jul 3, 2023
a954a2e
Merge branch 'main' into simmy-v8
vany0114 Jul 8, 2023
de989ef
WIP: adding unit tests
vany0114 Jul 8, 2023
15f2ccb
wrapping up behavior unit tests
vany0114 Jul 9, 2023
7dac89e
add missing parameters in builder extensions
vany0114 Jul 9, 2023
df62a10
* adding unit tests for outcome chaos strategy
vany0114 Jul 9, 2023
dc330ef
Merge branch 'main' into simmy-v8
vany0114 Jul 9, 2023
60db9d3
put back MonkeyStrategy generic implemetnation so that people can ext…
vany0114 Jul 9, 2023
c425004
Merge branch 'main' into simmy-v8
vany0114 Jul 10, 2023
07124ac
Merge branch 'main' into simmy-v8
vany0114 Aug 5, 2023
5b34067
Merge branch 'main' into simmy-v8
vany0114 Aug 5, 2023
0d6c306
fault unit tests
vany0114 Aug 7, 2023
adf8120
add result unit tests
vany0114 Aug 7, 2023
eb609fd
clean up
vany0114 Aug 7, 2023
93e0be8
Merge branch 'main' into simmy-v8
vany0114 Aug 7, 2023
979c573
rename OutcomeMonkeyStrategy to ReactiveMonkeyStrategy
vany0114 Aug 7, 2023
4723d6b
PR feedback part 1
vany0114 Aug 13, 2023
48d835b
PR feedback part 2
vany0114 Aug 13, 2023
c826db8
* refactor monkey strategies to use the new approach with reactive an…
vany0114 Aug 20, 2023
f3a62bb
update api file
vany0114 Aug 20, 2023
9fc7fde
Merge branch 'main' into simmy-v8
vany0114 Aug 20, 2023
b7c9b3a
wrapping up
vany0114 Aug 20, 2023
d054336
add more unit tests
vany0114 Aug 26, 2023
74da3de
Merge branch 'main' into simmy-v8
vany0114 Aug 26, 2023
28d3b0c
PR feedback
vany0114 Aug 27, 2023
d8286a4
fixes buld erros
vany0114 Aug 27, 2023
a21d1c3
Merge branch 'main' into simmy-v8
vany0114 Sep 3, 2023
c2ec5a5
pr feedback
vany0114 Sep 3, 2023
995294c
Merge branch 'main' into simmy-v8
vany0114 Sep 10, 2023
1eb39a6
fix PublicAPI.Unshipped.txt
vany0114 Sep 10, 2023
7d959ca
PR feedback: use FaultStrategyOptions to separate outcomes from fault…
vany0114 Sep 10, 2023
5959d83
more PR feedback
vany0114 Sep 10, 2023
7845c51
code coverage unit tests almost done
vany0114 Sep 11, 2023
1428577
* pr feedback
vany0114 Sep 18, 2023
0e8eda0
Merge branch 'main' into simmy-v8
vany0114 Sep 18, 2023
f6bee7b
100% coverage!
vany0114 Sep 18, 2023
48bda7c
add missing unit tests to kill survivor mutants
vany0114 Sep 19, 2023
d3d7ba5
Merge branch 'main' into simmy-v8
vany0114 Sep 19, 2023
ac0bba6
disable "once equality" for mutants that cannot be killed
vany0114 Sep 19, 2023
7d98bab
Merge branch 'main' into simmy-v8
vany0114 Sep 19, 2023
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
98 changes: 98 additions & 0 deletions src/Polly.Core/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,91 @@ Polly.Retry.RetryStrategyOptions<TResult>.ShouldHandle.set -> void
Polly.Retry.RetryStrategyOptions<TResult>.UseJitter.get -> bool
Polly.Retry.RetryStrategyOptions<TResult>.UseJitter.set -> void
Polly.RetryResiliencePipelineBuilderExtensions
Polly.Simmy.Behavior.BehaviorActionArguments
Polly.Simmy.Behavior.BehaviorActionArguments.BehaviorActionArguments() -> void
Polly.Simmy.Behavior.BehaviorActionArguments.BehaviorActionArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.Behavior.BehaviorActionArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Behavior.BehaviorStrategyOptions
Polly.Simmy.Behavior.BehaviorStrategyOptions.BehaviorAction.get -> System.Func<Polly.Simmy.Behavior.BehaviorActionArguments, System.Threading.Tasks.ValueTask>?
Polly.Simmy.Behavior.BehaviorStrategyOptions.BehaviorAction.set -> void
Polly.Simmy.Behavior.BehaviorStrategyOptions.BehaviorStrategyOptions() -> void
Polly.Simmy.Behavior.BehaviorStrategyOptions.OnBehaviorInjected.get -> System.Func<Polly.Simmy.Behavior.OnBehaviorInjectedArguments, System.Threading.Tasks.ValueTask>?
Polly.Simmy.Behavior.BehaviorStrategyOptions.OnBehaviorInjected.set -> void
Polly.Simmy.Behavior.OnBehaviorInjectedArguments
Polly.Simmy.Behavior.OnBehaviorInjectedArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Behavior.OnBehaviorInjectedArguments.OnBehaviorInjectedArguments() -> void
Polly.Simmy.Behavior.OnBehaviorInjectedArguments.OnBehaviorInjectedArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.BehaviorChaosPipelineBuilderExtensions
Polly.Simmy.EnabledGeneratorArguments
Polly.Simmy.EnabledGeneratorArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.EnabledGeneratorArguments.EnabledGeneratorArguments() -> void
Polly.Simmy.EnabledGeneratorArguments.EnabledGeneratorArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.InjectionRateGeneratorArguments
Polly.Simmy.InjectionRateGeneratorArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.InjectionRateGeneratorArguments.InjectionRateGeneratorArguments() -> void
Polly.Simmy.InjectionRateGeneratorArguments.InjectionRateGeneratorArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.Latency.LatencyGeneratorArguments
Polly.Simmy.Latency.LatencyGeneratorArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Latency.LatencyGeneratorArguments.LatencyGeneratorArguments() -> void
Polly.Simmy.Latency.LatencyGeneratorArguments.LatencyGeneratorArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.Latency.LatencyStrategyOptions
Polly.Simmy.Latency.LatencyStrategyOptions.Latency.get -> System.TimeSpan
Polly.Simmy.Latency.LatencyStrategyOptions.Latency.set -> void
Polly.Simmy.Latency.LatencyStrategyOptions.LatencyGenerator.get -> System.Func<Polly.Simmy.Latency.LatencyGeneratorArguments, System.Threading.Tasks.ValueTask<System.TimeSpan>>?
Polly.Simmy.Latency.LatencyStrategyOptions.LatencyGenerator.set -> void
Polly.Simmy.Latency.LatencyStrategyOptions.LatencyStrategyOptions() -> void
Polly.Simmy.Latency.LatencyStrategyOptions.OnLatency.get -> System.Func<Polly.Simmy.Latency.OnLatencyArguments, System.Threading.Tasks.ValueTask>?
Polly.Simmy.Latency.LatencyStrategyOptions.OnLatency.set -> void
Polly.Simmy.Latency.OnLatencyArguments
Polly.Simmy.Latency.OnLatencyArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Latency.OnLatencyArguments.Latency.get -> System.TimeSpan
Polly.Simmy.Latency.OnLatencyArguments.OnLatencyArguments() -> void
Polly.Simmy.Latency.OnLatencyArguments.OnLatencyArguments(Polly.ResilienceContext! context, System.TimeSpan latency) -> void
Polly.Simmy.LatencyChaosPipelineBuilderExtensions
Polly.Simmy.MonkeyStrategy
Polly.Simmy.MonkeyStrategy.EnabledGenerator.get -> System.Func<Polly.Simmy.EnabledGeneratorArguments, System.Threading.Tasks.ValueTask<bool>>!
Polly.Simmy.MonkeyStrategy.InjectionRateGenerator.get -> System.Func<Polly.Simmy.InjectionRateGeneratorArguments, System.Threading.Tasks.ValueTask<double>>!
Polly.Simmy.MonkeyStrategy.MonkeyStrategy(Polly.Simmy.MonkeyStrategyOptions! options) -> void
Polly.Simmy.MonkeyStrategy.ShouldInjectAsync(Polly.ResilienceContext! context) -> System.Threading.Tasks.ValueTask<bool>
Polly.Simmy.MonkeyStrategy<T>
Polly.Simmy.MonkeyStrategy<T>.EnabledGenerator.get -> System.Func<Polly.Simmy.EnabledGeneratorArguments, System.Threading.Tasks.ValueTask<bool>>!
Polly.Simmy.MonkeyStrategy<T>.InjectionRateGenerator.get -> System.Func<Polly.Simmy.InjectionRateGeneratorArguments, System.Threading.Tasks.ValueTask<double>>!
Polly.Simmy.MonkeyStrategy<T>.MonkeyStrategy(Polly.Simmy.MonkeyStrategyOptions! options) -> void
Polly.Simmy.MonkeyStrategy<T>.ShouldInjectAsync(Polly.ResilienceContext! context) -> System.Threading.Tasks.ValueTask<bool>
Polly.Simmy.MonkeyStrategyOptions
Polly.Simmy.MonkeyStrategyOptions.MonkeyStrategyOptions() -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>
Polly.Simmy.MonkeyStrategyOptions<TResult>.Enabled.get -> bool
Polly.Simmy.MonkeyStrategyOptions<TResult>.Enabled.set -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>.EnabledGenerator.get -> System.Func<Polly.Simmy.EnabledGeneratorArguments, System.Threading.Tasks.ValueTask<bool>>?
Polly.Simmy.MonkeyStrategyOptions<TResult>.EnabledGenerator.set -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>.InjectionRate.get -> double
Polly.Simmy.MonkeyStrategyOptions<TResult>.InjectionRate.set -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>.InjectionRateGenerator.get -> System.Func<Polly.Simmy.InjectionRateGeneratorArguments, System.Threading.Tasks.ValueTask<double>>?
Polly.Simmy.MonkeyStrategyOptions<TResult>.InjectionRateGenerator.set -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>.MonkeyStrategyOptions() -> void
Polly.Simmy.MonkeyStrategyOptions<TResult>.Randomizer.get -> System.Func<double>!
Polly.Simmy.MonkeyStrategyOptions<TResult>.Randomizer.set -> void
Polly.Simmy.OutcomeChaosPipelineBuilderExtensions
Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>
Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.OnOutcomeInjectedArguments() -> void
Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.OnOutcomeInjectedArguments(Polly.ResilienceContext! context, Polly.Outcome<TResult> outcome) -> void
Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>.Outcome.get -> Polly.Outcome<TResult>
Polly.Simmy.Outcomes.OutcomeGeneratorArguments
Polly.Simmy.Outcomes.OutcomeGeneratorArguments.Context.get -> Polly.ResilienceContext!
Polly.Simmy.Outcomes.OutcomeGeneratorArguments.OutcomeGeneratorArguments() -> void
Polly.Simmy.Outcomes.OutcomeGeneratorArguments.OutcomeGeneratorArguments(Polly.ResilienceContext! context) -> void
Polly.Simmy.Outcomes.OutcomeStrategyOptions
Polly.Simmy.Outcomes.OutcomeStrategyOptions.OutcomeStrategyOptions() -> void
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OnOutcomeInjected.get -> System.Func<Polly.Simmy.Outcomes.OnOutcomeInjectedArguments<TResult>, System.Threading.Tasks.ValueTask>?
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OnOutcomeInjected.set -> void
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.Outcome.get -> Polly.Outcome<TResult>?
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.Outcome.set -> void
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OutcomeGenerator.get -> System.Func<Polly.Simmy.Outcomes.OutcomeGeneratorArguments, System.Threading.Tasks.ValueTask<Polly.Outcome<TResult>?>>?
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OutcomeGenerator.set -> void
Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>.OutcomeStrategyOptions() -> void
Polly.StrategyBuilderContext
Polly.StrategyBuilderContext.Telemetry.get -> Polly.Telemetry.ResilienceStrategyTelemetry!
Polly.Telemetry.ExecutionAttemptArguments
Expand Down Expand Up @@ -414,6 +499,19 @@ static Polly.ResiliencePipelineBuilderExtensions.AddStrategy<TBuilder>(this TBui
static Polly.ResiliencePipelineBuilderExtensions.AddStrategy<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, System.Func<Polly.StrategyBuilderContext!, Polly.ResilienceStrategy<TResult>!>! factory, Polly.ResilienceStrategyOptions! options) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.RetryResiliencePipelineBuilderExtensions.AddRetry(this Polly.ResiliencePipelineBuilder! builder, Polly.Retry.RetryStrategyOptions! options) -> Polly.ResiliencePipelineBuilder!
static Polly.RetryResiliencePipelineBuilderExtensions.AddRetry<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, Polly.Retry.RetryStrategyOptions<TResult>! options) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.BehaviorChaosPipelineBuilderExtensions.AddChaosBehavior<TBuilder>(this TBuilder! builder, bool enabled, double injectionRate, System.Func<System.Threading.Tasks.ValueTask>! behavior) -> TBuilder!
static Polly.Simmy.BehaviorChaosPipelineBuilderExtensions.AddChaosBehavior<TBuilder>(this TBuilder! builder, Polly.Simmy.Behavior.BehaviorStrategyOptions! options) -> TBuilder!
static Polly.Simmy.LatencyChaosPipelineBuilderExtensions.AddChaosLatency<TBuilder>(this TBuilder! builder, bool enabled, double injectionRate, System.TimeSpan latency) -> TBuilder!
static Polly.Simmy.LatencyChaosPipelineBuilderExtensions.AddChaosLatency<TBuilder>(this TBuilder! builder, Polly.Simmy.Latency.LatencyStrategyOptions! options) -> TBuilder!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault(this Polly.ResiliencePipelineBuilder! builder, bool enabled, double injectionRate, System.Exception! fault) -> Polly.ResiliencePipelineBuilder!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault(this Polly.ResiliencePipelineBuilder! builder, bool enabled, double injectionRate, System.Func<System.Exception?>! faultGenerator) -> Polly.ResiliencePipelineBuilder!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault(this Polly.ResiliencePipelineBuilder! builder, Polly.Simmy.Outcomes.OutcomeStrategyOptions<System.Exception!>! options) -> Polly.ResiliencePipelineBuilder!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, bool enabled, double injectionRate, System.Exception! fault) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, bool enabled, double injectionRate, System.Func<System.Exception?>! faultGenerator) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosFault<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, Polly.Simmy.Outcomes.OutcomeStrategyOptions<System.Exception!>! options) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosResult<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, bool enabled, double injectionRate, System.Func<TResult?>! outcomeGenerator) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosResult<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, bool enabled, double injectionRate, TResult result) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.Simmy.OutcomeChaosPipelineBuilderExtensions.AddChaosResult<TResult>(this Polly.ResiliencePipelineBuilder<TResult>! builder, Polly.Simmy.Outcomes.OutcomeStrategyOptions<TResult>! options) -> Polly.ResiliencePipelineBuilder<TResult>!
static Polly.TimeoutResiliencePipelineBuilderExtensions.AddTimeout<TBuilder>(this TBuilder! builder, Polly.Timeout.TimeoutStrategyOptions! options) -> TBuilder!
static Polly.TimeoutResiliencePipelineBuilderExtensions.AddTimeout<TBuilder>(this TBuilder! builder, System.TimeSpan timeout) -> TBuilder!
static readonly Polly.ResiliencePipeline.Empty -> Polly.ResiliencePipeline!
Expand Down
20 changes: 20 additions & 0 deletions src/Polly.Core/Simmy/Behavior/BehaviorActionArguments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Polly.Simmy.Behavior;

#pragma warning disable CA1815 // Override equals and operator equals on value types

/// <summary>
/// Arguments used by the behavior chaos strategy to execute a user's delegate custom action.
/// </summary>
public readonly struct BehaviorActionArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="BehaviorActionArguments"/> struct.
/// </summary>
/// <param name="context">The context associated with the execution of a user-provided callback.</param>
public BehaviorActionArguments(ResilienceContext context) => Context = context;

/// <summary>
/// Gets the ResilienceContext instance.
/// </summary>
public ResilienceContext Context { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using Polly.Simmy.Behavior;

namespace Polly.Simmy;

/// <summary>
/// Extension methods for adding custom behaviors to a <see cref="ResiliencePipelineBuilder"/>.
/// </summary>
public static class BehaviorChaosPipelineBuilderExtensions
{
/// <summary>
/// Adds a behavior chaos strategy to the builder.
/// </summary>
/// <typeparam name="TBuilder">The builder type.</typeparam>
/// <param name="builder">The builder instance.</param>
/// <param name="enabled">A value that indicates whether or not the chaos strategy is enabled for a given execution.</param>
/// <param name="injectionRate">The injection rate for a given execution, which the value should be between [0, 1].</param>
vany0114 marked this conversation as resolved.
Show resolved Hide resolved
/// <param name="behavior">The behavior to be injected.</param>
/// <returns>The same builder instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when the options produced from the arguments are invalid.</exception>
public static TBuilder AddChaosBehavior<TBuilder>(this TBuilder builder, bool enabled, double injectionRate, Func<ValueTask> behavior)
where TBuilder : ResiliencePipelineBuilderBase
{
Guard.NotNull(builder);

return builder.AddChaosBehavior(new BehaviorStrategyOptions
{
Enabled = enabled,
InjectionRate = injectionRate,
BehaviorAction = (_) => behavior()
});
}

/// <summary>
/// Adds a behavior chaos strategy to the builder.
/// </summary>
/// <typeparam name="TBuilder">The builder type.</typeparam>
/// <param name="builder">The builder instance.</param>
/// <param name="options">The behavior options.</param>
/// <returns>The same builder instance.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="builder"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
/// <exception cref="ValidationException">Thrown when <paramref name="options"/> are invalid.</exception>
[UnconditionalSuppressMessage(
"Trimming",
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
Justification = "All options members preserved.")]
public static TBuilder AddChaosBehavior<TBuilder>(this TBuilder builder, BehaviorStrategyOptions options)
where TBuilder : ResiliencePipelineBuilderBase
{
Guard.NotNull(builder);
Guard.NotNull(options);

return builder.AddStrategy(context => new BehaviorChaosStrategy(options, context.Telemetry), options);
}
}
50 changes: 50 additions & 0 deletions src/Polly.Core/Simmy/Behavior/BehaviorChaosStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using Polly.Telemetry;

namespace Polly.Simmy.Behavior;

internal sealed class BehaviorChaosStrategy : MonkeyStrategy
{
private readonly ResilienceStrategyTelemetry _telemetry;

public BehaviorChaosStrategy(
BehaviorStrategyOptions options,
ResilienceStrategyTelemetry telemetry)
: base(options)
{
_telemetry = telemetry;
OnBehaviorInjected = options.OnBehaviorInjected;
Behavior = options.BehaviorAction!;
}

public Func<OnBehaviorInjectedArguments, ValueTask>? OnBehaviorInjected { get; }

public Func<BehaviorActionArguments, ValueTask> Behavior { get; }

protected internal override async ValueTask<Outcome<TResult>> ExecuteCore<TResult, TState>(
Func<ResilienceContext, TState, ValueTask<Outcome<TResult>>> callback,
ResilienceContext context,
TState state)
{
try
{
if (await ShouldInjectAsync(context).ConfigureAwait(context.ContinueOnCapturedContext))
{
await Behavior(new(context)).ConfigureAwait(context.ContinueOnCapturedContext);

var args = new OnBehaviorInjectedArguments(context);
_telemetry.Report(new(ResilienceEventSeverity.Warning, BehaviorConstants.OnBehaviorInjectedEvent), context, args);
vany0114 marked this conversation as resolved.
Show resolved Hide resolved

if (OnBehaviorInjected is not null)
{
await OnBehaviorInjected(args).ConfigureAwait(context.ContinueOnCapturedContext);
}
}

return await StrategyHelper.ExecuteCallbackSafeAsync(callback, context, state).ConfigureAwait(context.ContinueOnCapturedContext);
}
catch (OperationCanceledException e)
vany0114 marked this conversation as resolved.
Show resolved Hide resolved
{
return new Outcome<TResult>(e);
}
}
}
6 changes: 6 additions & 0 deletions src/Polly.Core/Simmy/Behavior/BehaviorConstants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Polly.Simmy.Behavior;

internal static class BehaviorConstants
{
public const string OnBehaviorInjectedEvent = "OnBehaviorInjected";
}
26 changes: 26 additions & 0 deletions src/Polly.Core/Simmy/Behavior/BehaviorStrategyOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;

namespace Polly.Simmy.Behavior;

/// <summary>
/// Represents the options for the Behavior chaos strategy.
/// </summary>
public class BehaviorStrategyOptions : MonkeyStrategyOptions
{
/// <summary>
/// Gets or sets the delegate that's raised when the custom behavior is injected.
/// </summary>
/// <remarks>
/// Defaults to <see langword="null"/>.
/// </remarks>
public Func<OnBehaviorInjectedArguments, ValueTask>? OnBehaviorInjected { get; set; }

/// <summary>
/// Gets or sets the custom behavior that is going to be injected for a given execution.
/// </summary>
/// <remarks>
/// Defaults to <see langword="null"/>.
/// </remarks>
[Required]
public Func<BehaviorActionArguments, ValueTask>? BehaviorAction { get; set; }
}
20 changes: 20 additions & 0 deletions src/Polly.Core/Simmy/Behavior/OnBehaviorInjectedArguments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Polly.Simmy.Behavior;

#pragma warning disable CA1815 // Override equals and operator equals on value types

/// <summary>
/// Arguments used by the behavior chaos strategy to notify that a custom behavior was injected.
/// </summary>
public readonly struct OnBehaviorInjectedArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="OnBehaviorInjectedArguments"/> struct.
/// </summary>
/// <param name="context">The context associated with the execution of a user-provided callback.</param>
public OnBehaviorInjectedArguments(ResilienceContext context) => Context = context;

/// <summary>
/// Gets the ResilienceContext instance.
/// </summary>
public ResilienceContext Context { get; }
}
20 changes: 20 additions & 0 deletions src/Polly.Core/Simmy/EnabledGeneratorArguments.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace Polly.Simmy;

#pragma warning disable CA1815 // Override equals and operator equals on value types

/// <summary>
/// Defines the arguments for the <see cref="MonkeyStrategyOptions{TResult}.EnabledGenerator"/>.
/// </summary>
public readonly struct EnabledGeneratorArguments
{
/// <summary>
/// Initializes a new instance of the <see cref="EnabledGeneratorArguments"/> struct.
/// </summary>
/// <param name="context">The resilience context intance.</param>
vany0114 marked this conversation as resolved.
Show resolved Hide resolved
public EnabledGeneratorArguments(ResilienceContext context) => Context = context;

/// <summary>
/// Gets the ResilienceContext instance.
/// </summary>
public ResilienceContext Context { get; }
}
Loading