forked from App-vNext/Polly
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChaos.Outcome.cs
More file actions
118 lines (103 loc) · 5.29 KB
/
Chaos.Outcome.cs
File metadata and controls
118 lines (103 loc) · 5.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System.Net;
using System.Net.Http;
using Polly.Retry;
using Polly.Simmy;
using Polly.Simmy.Outcomes;
namespace Snippets.Docs;
#pragma warning disable CA5394 // Do not use insecure randomness
internal static partial class Chaos
{
public static void OutcomeUsage()
{
#region chaos-outcome-usage
// To use OutcomeGenerator<T> to register the results and exceptions to be injected (equal probability)
var optionsWithResultGenerator = new ChaosOutcomeStrategyOptions<HttpResponseMessage>
{
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
.AddResult(() => new HttpResponseMessage(HttpStatusCode.TooManyRequests))
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError))
.AddException(() => new HttpRequestException("Chaos request exception.")),
InjectionRate = 0.1
};
// To get notifications when a result is injected
var optionsOnBehaviorInjected = new ChaosOutcomeStrategyOptions<HttpResponseMessage>
{
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)),
InjectionRate = 0.1,
OnOutcomeInjected = static args =>
{
Console.WriteLine($"OnBehaviorInjected, Outcome: {args.Outcome.Result}, Operation: {args.Context.OperationKey}.");
return default;
}
};
// Add a result strategy with a ChaosOutcomeStrategyOptions{<TResult>} instance to the pipeline
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosOutcome(optionsWithResultGenerator);
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosOutcome(optionsOnBehaviorInjected);
// There are also a couple of handy overloads to inject the chaos easily
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosOutcome(0.1, () => new HttpResponseMessage(HttpStatusCode.TooManyRequests));
#endregion
#region chaos-outcome-execution
var pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
ShouldHandle = static args => args.Outcome switch
{
{ Result.StatusCode: HttpStatusCode.InternalServerError } => PredicateResult.True(),
_ => PredicateResult.False()
},
BackoffType = DelayBackoffType.Exponential,
UseJitter = true,
MaxRetryAttempts = 4,
Delay = TimeSpan.FromSeconds(3),
})
.AddChaosOutcome(new ChaosOutcomeStrategyOptions<HttpResponseMessage> // Chaos strategies are usually placed as the last ones in the pipeline
{
OutcomeGenerator = static args =>
{
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
return Outcome.FromResultAsValueTask(response);
},
InjectionRate = 0.1
})
.Build();
#endregion
}
public static void OutcomeGenerator()
{
#region chaos-outcome-generator-class
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddChaosOutcome(new ChaosOutcomeStrategyOptions<HttpResponseMessage>
{
// Use OutcomeGenerator<T> to register the results and exceptions to be injected
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)) // Result generator
.AddResult(() => new HttpResponseMessage(HttpStatusCode.TooManyRequests), weight: 50) // Result generator with weight
.AddResult(context => CreateResultFromContext(context)) // Access the ResilienceContext to create result
.AddException<HttpRequestException>(), // You can also register exceptions
});
#endregion
}
public static void OutcomeGeneratorDelegates()
{
#region chaos-outcome-generator-delegate
new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddChaosOutcome(new ChaosOutcomeStrategyOptions<HttpResponseMessage>
{
// The same behavior can be achieved with delegates
OutcomeGenerator = args =>
{
Outcome<HttpResponseMessage> outcome = Random.Shared.Next(350) switch
{
< 100 => Outcome.FromResult(new HttpResponseMessage(HttpStatusCode.InternalServerError)),
< 150 => Outcome.FromResult(new HttpResponseMessage(HttpStatusCode.TooManyRequests)),
< 250 => Outcome.FromResult(CreateResultFromContext(args.Context)),
_ => Outcome.FromException<HttpResponseMessage>(new TimeoutException())
};
return ValueTask.FromResult(outcome);
}
});
#endregion
}
private static HttpResponseMessage CreateResultFromContext(ResilienceContext context) => new(HttpStatusCode.TooManyRequests);
}