Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Polly-Contrib/Simmy/llms.txt

Use this file to discover all available pages before exploring further.

The InjectLatency policy adds an artificial delay before the wrapped call executes. This makes it the ideal tool for testing how your application responds to sluggish dependencies: does a timeout policy fire at the right threshold? Does a circuit breaker open after repeated slow responses? Does your UI remain responsive? Simmy handles all of this without needing a real slow service — you control the delay, the injection rate, and whether the policy is active at all. Latency injection policies are also cancellable: if a CancellationToken is signalled during the injected delay (for example, by an outer timeout policy), Simmy cancels the sleep immediately rather than blocking until the full delay elapses.

Factory method signatures

// Synchronous, non-generic — wraps void or any return type
InjectLatencyPolicy MonkeyPolicy.InjectLatency(
    Action<InjectLatencyOptions> configureOptions
)

// Synchronous, typed — wraps calls returning TResult
InjectLatencyPolicy<TResult> MonkeyPolicy.InjectLatency<TResult>(
    Action<InjectLatencyOptions> configureOptions
)

// Asynchronous — wraps async calls
AsyncInjectLatencyPolicy MonkeyPolicy.InjectLatencyAsync(
    Action<InjectLatencyAsyncOptions> configureOptions
)

Quick start

1

Decide on a latency and injection rate

Choose how long the artificial delay should be and on what proportion of calls it fires. A 5-second delay on 10% of calls is a realistic starting point.
var isEnabled = true;
2

Build the chaos policy

Configure the latency value, injection rate, and enabled flag through the fluent builder.
var chaosPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled(isEnabled)
);
An injection rate of 0.1 means 10% of calls will be delayed by 5 seconds before the real code runs. Setting .Enabled(isEnabled) ties the active state to the isEnabled variable — flip it to false to pause chaos without changing any policy configuration.
3

Execute through the policy

Run your code through the policy exactly as with any other Polly policy.
chaosPolicy.Execute(() => someMethod());
On roughly 1 in 10 calls, Simmy sleeps for 5 seconds before calling someMethod(). Your outer timeout or circuit-breaker policies observe this pause as if it were a genuine slow dependency.

Fluent option methods

.Latency(TimeSpan)

Provides a fixed delay to inject. Simmy sleeps for this duration before the wrapped call.

.InjectionRate(double)

A value between 0.0 and 1.0 controlling how often the delay is injected.

.Enabled() / .Enabled(bool)

Activates the monkey policy. Pass false or a variable to pause injection at runtime.

Dynamic latency with a delegate

Supply a Func<Context, CancellationToken, TimeSpan> to vary the injected delay per call. This lets you simulate jitter or model degrading performance under load.
var random = new Random();
var chaosPolicy = MonkeyPolicy.InjectLatency(with =>
    with.Latency((ctx, ct) => TimeSpan.FromSeconds(random.Next(1, 10)))
        .InjectionRate(0.2)
        .Enabled()
);

Async variant with PolicyWrap

The async variant accepts InjectLatencyAsyncOptions (where EnabledWhen takes a Func<Context, CancellationToken, Task<bool>>) and returns an AsyncInjectLatencyPolicy. It integrates naturally into async PolicyWrap chains.
var chaosLatencyPolicy = MonkeyPolicy.InjectLatencyAsync(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled()
);

var policyWrap = Policy.WrapAsync(fallbackPolicy, timeoutPolicy, chaosLatencyPolicy);

var result = await policyWrap.ExecuteAsync(
    token => service.GetFoo(parametersBar, token),
    myCancellationToken
);
Place the InjectLatency policy innermost in the PolicyWrap. This way the outer timeout policy sees the injected delay as a real slow response and trips at its configured threshold — which is exactly the behaviour you want to verify.

Testing timeout thresholds

Latency injection is the most direct way to test that a Polly.Timeout policy fires at the right threshold and that downstream policies handle the resulting TimeoutRejectedException correctly.
var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(3));

var chaosLatencyPolicy = MonkeyPolicy.InjectLatencyAsync(with =>
    with.Latency(TimeSpan.FromSeconds(10))  // deliberately exceeds the 3-second timeout
        .InjectionRate(0.5)
        .Enabled()
);

// Innermost chaos, then timeout, then fallback
var policyWrap = Policy.WrapAsync(fallbackPolicy, timeoutPolicy, chaosLatencyPolicy);
Try varying the injected latency above and below your timeout threshold. A delay just under the limit exercises normal slow-path handling; a delay just over it verifies your timeout and fallback chain fires correctly.

Cancellation support

Latency injection policies respect the CancellationToken passed to Execute/ExecuteAsync. If the token is cancelled during the injected sleep — for example, because an outer TimeoutPolicy cancelled the execution — Simmy aborts the delay immediately and propagates the cancellation.
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));

// The 10-second injected delay will be cut short when cts cancels at 2 seconds
await chaosLatencyPolicy.ExecuteAsync(
    ct => service.GetDataAsync(ct),
    cts.Token
);

Typed variant

When wrapping calls that return a value, use MonkeyPolicy.InjectLatency<TResult>, which returns InjectLatencyPolicy<TResult> and works identically but preserves the return type.
var chaosPolicy = MonkeyPolicy.InjectLatency<HttpResponseMessage>(with =>
    with.Latency(TimeSpan.FromSeconds(5))
        .InjectionRate(0.1)
        .Enabled()
);

var response = chaosPolicy.Execute(() => httpClient.GetAsync("/api/data").Result);

Reference

See Policy Options for the full reference on shared fluent options, including Context-driven delegate overloads for InjectionRate and EnabledWhen.

Build docs developers (and LLMs) love