Use new chaos APIs to simplify the usage examples (#1912)
This commit is contained in:
Родитель
cf008353cd
Коммит
2e1a2a56e8
|
@ -459,6 +459,10 @@ Rate limiter strategy throws `RateLimiterRejectedException` if execution is reje
|
|||
|
||||
For more details, visit the [rate limiter strategy](https://www.pollydocs.org/strategies/rate-limiter) documentation.
|
||||
|
||||
## Chaos engineering
|
||||
|
||||
Starting with version `8.3.0`, Polly has integrated [Simmy](https://github.com/Polly-Contrib/Simmy), a chaos engineering library, directly into its core. For more information, please refer to the dedicated [chaos engineering documentation](https://www.pollydocs.org/chaos/).
|
||||
|
||||
## Next steps
|
||||
|
||||
To learn more about Polly, visit [pollydocs.org][polly-docs].
|
||||
|
|
|
@ -17,7 +17,7 @@ The behavior chaos strategy is designed to inject custom behaviors into system o
|
|||
|
||||
<!-- snippet: chaos-behavior-usage -->
|
||||
```cs
|
||||
// To use a custom function to generate the behavior to inject.
|
||||
// To use a custom delegated for injected behavior
|
||||
var optionsWithBehaviorGenerator = new BehaviorStrategyOptions
|
||||
{
|
||||
BehaviorAction = static args => RestartRedisVM(),
|
||||
|
@ -42,7 +42,7 @@ var optionsOnBehaviorInjected = new BehaviorStrategyOptions
|
|||
new ResiliencePipelineBuilder().AddChaosBehavior(optionsWithBehaviorGenerator);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosBehavior(optionsOnBehaviorInjected);
|
||||
|
||||
// There are also a handy overload to inject the chaos easily.
|
||||
// There are also a handy overload to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisVM);
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
|
|
@ -17,15 +17,17 @@ The fault chaos strategy is designed to introduce faults (exceptions) into the s
|
|||
|
||||
<!-- snippet: chaos-fault-usage -->
|
||||
```cs
|
||||
// 10% of invocations will be randomly affected.
|
||||
// 10% of invocations will be randomly affected and one of the exceptions will be thrown (equal probability).
|
||||
var optionsBasic = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args => new ValueTask<Exception?>(new InvalidOperationException("Dummy exception")),
|
||||
FaultGenerator = new FaultGenerator()
|
||||
.AddException<InvalidOperationException>() // Uses default constructor
|
||||
.AddException(() => new TimeoutException("Chaos timeout injected.")), // Custom exception generator
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1
|
||||
};
|
||||
|
||||
// To use a custom function to generate the fault to inject.
|
||||
// To use a custom delegate to generate the fault to be injected
|
||||
var optionsWithFaultGenerator = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args =>
|
||||
|
@ -34,7 +36,9 @@ var optionsWithFaultGenerator = new FaultStrategyOptions
|
|||
{
|
||||
"DataLayer" => new TimeoutException(),
|
||||
"ApplicationLayer" => new InvalidOperationException(),
|
||||
_ => null // When the fault generator returns null the strategy won't inject any fault and it will just invoke the user's callback
|
||||
// When the fault generator returns null, the strategy won't inject
|
||||
// any fault and just invokes the user's callback.
|
||||
_ => null
|
||||
};
|
||||
|
||||
return new ValueTask<Exception?>(exception);
|
||||
|
@ -46,7 +50,7 @@ var optionsWithFaultGenerator = new FaultStrategyOptions
|
|||
// To get notifications when a fault is injected
|
||||
var optionsOnFaultInjected = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args => new ValueTask<Exception?>(new InvalidOperationException("Dummy exception")),
|
||||
FaultGenerator = new FaultGenerator().AddException<InvalidOperationException>(),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1,
|
||||
OnFaultInjected = static args =>
|
||||
|
@ -60,7 +64,7 @@ var optionsOnFaultInjected = new FaultStrategyOptions
|
|||
new ResiliencePipelineBuilder().AddChaosFault(optionsBasic);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosFault(optionsWithFaultGenerator);
|
||||
|
||||
// There are also a couple of handy overloads to inject the chaos easily.
|
||||
// There are also a couple of handy overloads to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosFault(0.1, () => new InvalidOperationException("Dummy exception"));
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
@ -136,3 +140,53 @@ sequenceDiagram
|
|||
F->>P: Throws injected Fault
|
||||
P->>C: Propagates Exception
|
||||
```
|
||||
|
||||
## Generating faults
|
||||
|
||||
To generate a fault, you need to specify a `FaultGenerator` delegate. You have the following options as to how you customize this delegate:
|
||||
|
||||
### Use `FaultGenerator` class to generate faults
|
||||
|
||||
The `FaultGenerator` is convenience API that allows you to specify what faults (exceptions) are to be injected. Additionally, it also allows assigning weight to each registered fault.
|
||||
|
||||
<!-- snippet: chaos-fault-generator-class -->
|
||||
```cs
|
||||
new ResiliencePipelineBuilder()
|
||||
.AddChaosFault(new FaultStrategyOptions
|
||||
{
|
||||
// Use FaultGenerator to register exceptions to be injected
|
||||
FaultGenerator = new FaultGenerator()
|
||||
.AddException<InvalidOperationException>() // Uses default constructor
|
||||
.AddException(() => new TimeoutException("Chaos timeout injected.")) // Custom exception generator
|
||||
.AddException(context => CreateExceptionFromContext(context)) // Access the ResilienceContext
|
||||
.AddException<TimeoutException>(weight: 50), // Assign weight to the exception, default is 100
|
||||
});
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
||||
### Use delegates to generate faults
|
||||
|
||||
Delegates give you the most flexibility at the expense of slightly more complicated syntax. Delegates also support asynchronous fault generation, if you ever need that possibility.
|
||||
|
||||
<!-- snippet: chaos-fault-generator-delegate -->
|
||||
```cs
|
||||
new ResiliencePipelineBuilder()
|
||||
.AddChaosFault(new FaultStrategyOptions
|
||||
{
|
||||
// The same behavior can be achieved with delegates
|
||||
FaultGenerator = args =>
|
||||
{
|
||||
Exception? exception = Random.Shared.Next(350) switch
|
||||
{
|
||||
< 100 => new InvalidOperationException(),
|
||||
< 200 => new TimeoutException("Chaos timeout injected."),
|
||||
< 300 => CreateExceptionFromContext(args.Context),
|
||||
< 350 => new TimeoutException(),
|
||||
_ => null
|
||||
};
|
||||
|
||||
return new ValueTask<Exception?>(exception);
|
||||
}
|
||||
});
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
|
|
@ -48,7 +48,7 @@ All the strategies' options implement the [`MonkeyStrategyOptions`](xref:Polly.S
|
|||
|
||||
| Property | Default Value | Description |
|
||||
|--------------------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `InjectionRate` | 0.001 ms | A decimal between 0 and 1 inclusive. The strategy will inject the chaos, randomly, that proportion of the time, e.g.: if 0.2, twenty percent of calls will be randomly affected; if 0.01, one percent of calls; if 1, all calls. |
|
||||
| `InjectionRate` | 0.001 | A decimal between 0 and 1 inclusive. The strategy will inject the chaos, randomly, that proportion of the time, e.g.: if 0.2, twenty percent of calls will be randomly affected; if 0.01, one percent of calls; if 1, all calls. |
|
||||
| `InjectionRateGenerator` | `null` | Generates the injection rate for a given execution, which the value should be between [0, 1] (inclusive). |
|
||||
| `Enabled` | `false` | Determines whether the strategy is enabled or not. |
|
||||
| `EnabledGenerator` | `null` | The generator that indicates whether the chaos strategy is enabled for a given execution. |
|
||||
|
|
|
@ -21,7 +21,7 @@ The latency chaos strategy is designed to introduce controlled delays into syste
|
|||
// See https://www.pollydocs.org/chaos/latency#defaults for defaults.
|
||||
var optionsDefault = new LatencyStrategyOptions();
|
||||
|
||||
// 10% of invocations will be randomly affected.
|
||||
// 10% of invocations will be randomly affected
|
||||
var basicOptions = new LatencyStrategyOptions
|
||||
{
|
||||
Latency = TimeSpan.FromSeconds(30),
|
||||
|
@ -29,7 +29,7 @@ var basicOptions = new LatencyStrategyOptions
|
|||
InjectionRate = 0.1
|
||||
};
|
||||
|
||||
// To use a custom function to generate the latency to inject.
|
||||
// To use a custom function to generate the latency to inject
|
||||
var optionsWithLatencyGenerator = new LatencyStrategyOptions
|
||||
{
|
||||
LatencyGenerator = static args =>
|
||||
|
@ -38,7 +38,9 @@ var optionsWithLatencyGenerator = new LatencyStrategyOptions
|
|||
{
|
||||
"DataLayer" => TimeSpan.FromMilliseconds(500),
|
||||
"ApplicationLayer" => TimeSpan.FromSeconds(2),
|
||||
_ => TimeSpan.Zero // When the latency generator returns Zero the strategy won't inject any delay and it will just invoke the user's callback
|
||||
// When the latency generator returns Zero, the strategy
|
||||
// won't inject any delay and just invokes the user's callback.
|
||||
_ => TimeSpan.Zero
|
||||
};
|
||||
|
||||
return new ValueTask<TimeSpan>(latency);
|
||||
|
@ -64,7 +66,7 @@ var optionsOnBehaviorInjected = new LatencyStrategyOptions
|
|||
new ResiliencePipelineBuilder().AddChaosLatency(optionsDefault);
|
||||
new ResiliencePipelineBuilder<HttpStatusCode>().AddChaosLatency(optionsWithLatencyGenerator);
|
||||
|
||||
// There are also a handy overload to inject the chaos easily.
|
||||
// There are also a handy overload to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosLatency(0.1, TimeSpan.FromSeconds(30));
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
|
|
@ -19,14 +19,13 @@ The outcome chaos strategy is designed to inject or substitute fake results into
|
|||
|
||||
<!-- snippet: chaos-result-usage -->
|
||||
```cs
|
||||
// To use a custom function to generate the result to inject.
|
||||
// To use OutcomeGenerator<T> to register the results and exceptions to be injected (equal probability)
|
||||
var optionsWithResultGenerator = new OutcomeStrategyOptions<HttpResponseMessage>
|
||||
{
|
||||
OutcomeGenerator = static args =>
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||
return new ValueTask<Outcome<HttpResponseMessage>?>(Outcome.FromResult(response));
|
||||
},
|
||||
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.TooManyRequests))
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError))
|
||||
.AddException(() => new HttpRequestException("Chaos request exception.")),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1
|
||||
};
|
||||
|
@ -34,11 +33,8 @@ var optionsWithResultGenerator = new OutcomeStrategyOptions<HttpResponseMessage>
|
|||
// To get notifications when a result is injected
|
||||
var optionsOnBehaviorInjected = new OutcomeStrategyOptions<HttpResponseMessage>
|
||||
{
|
||||
OutcomeGenerator = static args =>
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||
return new ValueTask<Outcome<HttpResponseMessage>?>(Outcome.FromResult(response));
|
||||
},
|
||||
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1,
|
||||
OnOutcomeInjected = static args =>
|
||||
|
@ -52,7 +48,7 @@ var optionsOnBehaviorInjected = new OutcomeStrategyOptions<HttpResponseMessage>
|
|||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(optionsWithResultGenerator);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(optionsOnBehaviorInjected);
|
||||
|
||||
// There are also a couple of handy overloads to inject the chaos easily.
|
||||
// There are also a couple of handy overloads to inject the chaos easily
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(0.1, () => new HttpResponseMessage(HttpStatusCode.TooManyRequests));
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
@ -136,3 +132,53 @@ sequenceDiagram
|
|||
B->>P: Returns result
|
||||
P->>C: Returns result
|
||||
```
|
||||
|
||||
## Generating outcomes
|
||||
|
||||
To generate a faulted outcome (result or exception), you need to specify a `OutcomeGenerator` delegate. You have the following options as to how you customize this delegate:
|
||||
|
||||
### Use `OutcomeGenerator<T>` class to generate outcomes
|
||||
|
||||
The `OutcomeGenerator<T>` is a convenience API that allows you to specify what outcomes (results or exceptions) are to be injected. Additionally, it also allows assigning weight to each registered outcome.
|
||||
|
||||
<!-- snippet: chaos-outcome-generator-class -->
|
||||
```cs
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>()
|
||||
.AddChaosResult(new OutcomeStrategyOptions<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
|
||||
});
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
||||
### Use delegates to generate faults
|
||||
|
||||
Delegates give you the most flexibility at the expense of slightly more complicated syntax. Delegates also support asynchronous outcome generation, if you ever need that possibility.
|
||||
|
||||
<!-- snippet: chaos-outcome-generator-delegate -->
|
||||
```cs
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>()
|
||||
.AddChaosResult(new OutcomeStrategyOptions<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)),
|
||||
< 350 => Outcome.FromException<HttpResponseMessage>(new TimeoutException()),
|
||||
_ => null
|
||||
};
|
||||
|
||||
return ValueTask.FromResult(outcome);
|
||||
}
|
||||
});
|
||||
```
|
||||
<!-- endSnippet -->
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
- name: Advanced topics
|
||||
expanded: true
|
||||
items:
|
||||
- name: Telemetry and monitoring
|
||||
- name: Telemetry
|
||||
href: advanced/telemetry.md
|
||||
- name: Dependency injection
|
||||
href: advanced/dependency-injection.md
|
||||
|
|
|
@ -12,7 +12,7 @@ internal static partial class Chaos
|
|||
static ValueTask RestartRedisVM() => ValueTask.CompletedTask;
|
||||
|
||||
#region chaos-behavior-usage
|
||||
// To use a custom function to generate the behavior to inject.
|
||||
// To use a custom delegated for injected behavior
|
||||
var optionsWithBehaviorGenerator = new BehaviorStrategyOptions
|
||||
{
|
||||
BehaviorAction = static args => RestartRedisVM(),
|
||||
|
@ -37,7 +37,7 @@ internal static partial class Chaos
|
|||
new ResiliencePipelineBuilder().AddChaosBehavior(optionsWithBehaviorGenerator);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosBehavior(optionsOnBehaviorInjected);
|
||||
|
||||
// There are also a handy overload to inject the chaos easily.
|
||||
// There are also a handy overload to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosBehavior(0.05, RestartRedisVM);
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -5,20 +5,24 @@ using Polly.Simmy.Fault;
|
|||
|
||||
namespace Snippets.Docs;
|
||||
|
||||
#pragma warning disable CA5394 // Do not use insecure randomness
|
||||
|
||||
internal static partial class Chaos
|
||||
{
|
||||
public static void FaultUsage()
|
||||
{
|
||||
#region chaos-fault-usage
|
||||
// 10% of invocations will be randomly affected.
|
||||
// 10% of invocations will be randomly affected and one of the exceptions will be thrown (equal probability).
|
||||
var optionsBasic = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args => new ValueTask<Exception?>(new InvalidOperationException("Dummy exception")),
|
||||
FaultGenerator = new FaultGenerator()
|
||||
.AddException<InvalidOperationException>() // Uses default constructor
|
||||
.AddException(() => new TimeoutException("Chaos timeout injected.")), // Custom exception generator
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1
|
||||
};
|
||||
|
||||
// To use a custom function to generate the fault to inject.
|
||||
// To use a custom delegate to generate the fault to be injected
|
||||
var optionsWithFaultGenerator = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args =>
|
||||
|
@ -27,7 +31,9 @@ internal static partial class Chaos
|
|||
{
|
||||
"DataLayer" => new TimeoutException(),
|
||||
"ApplicationLayer" => new InvalidOperationException(),
|
||||
_ => null // When the fault generator returns null the strategy won't inject any fault and it will just invoke the user's callback
|
||||
// When the fault generator returns null, the strategy won't inject
|
||||
// any fault and just invokes the user's callback.
|
||||
_ => null
|
||||
};
|
||||
|
||||
return new ValueTask<Exception?>(exception);
|
||||
|
@ -39,7 +45,7 @@ internal static partial class Chaos
|
|||
// To get notifications when a fault is injected
|
||||
var optionsOnFaultInjected = new FaultStrategyOptions
|
||||
{
|
||||
FaultGenerator = static args => new ValueTask<Exception?>(new InvalidOperationException("Dummy exception")),
|
||||
FaultGenerator = new FaultGenerator().AddException<InvalidOperationException>(),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1,
|
||||
OnFaultInjected = static args =>
|
||||
|
@ -53,7 +59,7 @@ internal static partial class Chaos
|
|||
new ResiliencePipelineBuilder().AddChaosFault(optionsBasic);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosFault(optionsWithFaultGenerator);
|
||||
|
||||
// There are also a couple of handy overloads to inject the chaos easily.
|
||||
// There are also a couple of handy overloads to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosFault(0.1, () => new InvalidOperationException("Dummy exception"));
|
||||
#endregion
|
||||
|
||||
|
@ -76,4 +82,50 @@ internal static partial class Chaos
|
|||
.Build();
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static void FaultGenerator()
|
||||
{
|
||||
#region chaos-fault-generator-class
|
||||
|
||||
new ResiliencePipelineBuilder()
|
||||
.AddChaosFault(new FaultStrategyOptions
|
||||
{
|
||||
// Use FaultGenerator to register exceptions to be injected
|
||||
FaultGenerator = new FaultGenerator()
|
||||
.AddException<InvalidOperationException>() // Uses default constructor
|
||||
.AddException(() => new TimeoutException("Chaos timeout injected.")) // Custom exception generator
|
||||
.AddException(context => CreateExceptionFromContext(context)) // Access the ResilienceContext
|
||||
.AddException<TimeoutException>(weight: 50), // Assign weight to the exception, default is 100
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static void FaultGeneratorDelegates()
|
||||
{
|
||||
#region chaos-fault-generator-delegate
|
||||
|
||||
new ResiliencePipelineBuilder()
|
||||
.AddChaosFault(new FaultStrategyOptions
|
||||
{
|
||||
// The same behavior can be achieved with delegates
|
||||
FaultGenerator = args =>
|
||||
{
|
||||
Exception? exception = Random.Shared.Next(350) switch
|
||||
{
|
||||
< 100 => new InvalidOperationException(),
|
||||
< 200 => new TimeoutException("Chaos timeout injected."),
|
||||
< 300 => CreateExceptionFromContext(args.Context),
|
||||
< 350 => new TimeoutException(),
|
||||
_ => null
|
||||
};
|
||||
|
||||
return new ValueTask<Exception?>(exception);
|
||||
}
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
private static Exception CreateExceptionFromContext(ResilienceContext context) => new InvalidOperationException();
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ internal static partial class Chaos
|
|||
// See https://www.pollydocs.org/chaos/latency#defaults for defaults.
|
||||
var optionsDefault = new LatencyStrategyOptions();
|
||||
|
||||
// 10% of invocations will be randomly affected.
|
||||
// 10% of invocations will be randomly affected
|
||||
var basicOptions = new LatencyStrategyOptions
|
||||
{
|
||||
Latency = TimeSpan.FromSeconds(30),
|
||||
|
@ -23,7 +23,7 @@ internal static partial class Chaos
|
|||
InjectionRate = 0.1
|
||||
};
|
||||
|
||||
// To use a custom function to generate the latency to inject.
|
||||
// To use a custom function to generate the latency to inject
|
||||
var optionsWithLatencyGenerator = new LatencyStrategyOptions
|
||||
{
|
||||
LatencyGenerator = static args =>
|
||||
|
@ -32,7 +32,9 @@ internal static partial class Chaos
|
|||
{
|
||||
"DataLayer" => TimeSpan.FromMilliseconds(500),
|
||||
"ApplicationLayer" => TimeSpan.FromSeconds(2),
|
||||
_ => TimeSpan.Zero // When the latency generator returns Zero the strategy won't inject any delay and it will just invoke the user's callback
|
||||
// When the latency generator returns Zero, the strategy
|
||||
// won't inject any delay and just invokes the user's callback.
|
||||
_ => TimeSpan.Zero
|
||||
};
|
||||
|
||||
return new ValueTask<TimeSpan>(latency);
|
||||
|
@ -58,7 +60,7 @@ internal static partial class Chaos
|
|||
new ResiliencePipelineBuilder().AddChaosLatency(optionsDefault);
|
||||
new ResiliencePipelineBuilder<HttpStatusCode>().AddChaosLatency(optionsWithLatencyGenerator);
|
||||
|
||||
// There are also a handy overload to inject the chaos easily.
|
||||
// There are also a handy overload to inject the chaos easily
|
||||
new ResiliencePipelineBuilder().AddChaosLatency(0.1, TimeSpan.FromSeconds(30));
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -6,19 +6,20 @@ using Polly.Simmy.Outcomes;
|
|||
|
||||
namespace Snippets.Docs;
|
||||
|
||||
#pragma warning disable CA5394 // Do not use insecure randomness
|
||||
|
||||
internal static partial class Chaos
|
||||
{
|
||||
public static void ResultUsage()
|
||||
{
|
||||
#region chaos-result-usage
|
||||
// To use a custom function to generate the result to inject.
|
||||
// To use OutcomeGenerator<T> to register the results and exceptions to be injected (equal probability)
|
||||
var optionsWithResultGenerator = new OutcomeStrategyOptions<HttpResponseMessage>
|
||||
{
|
||||
OutcomeGenerator = static args =>
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||
return new ValueTask<Outcome<HttpResponseMessage>?>(Outcome.FromResult(response));
|
||||
},
|
||||
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.TooManyRequests))
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError))
|
||||
.AddException(() => new HttpRequestException("Chaos request exception.")),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1
|
||||
};
|
||||
|
@ -26,11 +27,8 @@ internal static partial class Chaos
|
|||
// To get notifications when a result is injected
|
||||
var optionsOnBehaviorInjected = new OutcomeStrategyOptions<HttpResponseMessage>
|
||||
{
|
||||
OutcomeGenerator = static args =>
|
||||
{
|
||||
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
|
||||
return new ValueTask<Outcome<HttpResponseMessage>?>(Outcome.FromResult(response));
|
||||
},
|
||||
OutcomeGenerator = new OutcomeGenerator<HttpResponseMessage>()
|
||||
.AddResult(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)),
|
||||
Enabled = true,
|
||||
InjectionRate = 0.1,
|
||||
OnOutcomeInjected = static args =>
|
||||
|
@ -44,7 +42,7 @@ internal static partial class Chaos
|
|||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(optionsWithResultGenerator);
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(optionsOnBehaviorInjected);
|
||||
|
||||
// There are also a couple of handy overloads to inject the chaos easily.
|
||||
// There are also a couple of handy overloads to inject the chaos easily
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>().AddChaosResult(0.1, () => new HttpResponseMessage(HttpStatusCode.TooManyRequests));
|
||||
#endregion
|
||||
|
||||
|
@ -75,4 +73,50 @@ internal static partial class Chaos
|
|||
.Build();
|
||||
#endregion
|
||||
}
|
||||
|
||||
public static void OutcomeGenerator()
|
||||
{
|
||||
#region chaos-outcome-generator-class
|
||||
|
||||
new ResiliencePipelineBuilder<HttpResponseMessage>()
|
||||
.AddChaosResult(new OutcomeStrategyOptions<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>()
|
||||
.AddChaosResult(new OutcomeStrategyOptions<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)),
|
||||
< 350 => Outcome.FromException<HttpResponseMessage>(new TimeoutException()),
|
||||
_ => null
|
||||
};
|
||||
|
||||
return ValueTask.FromResult(outcome);
|
||||
}
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
private static HttpResponseMessage CreateResultFromContext(ResilienceContext context) => new(HttpStatusCode.TooManyRequests);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче