-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathAsyncMonkeyEngine.cs
100 lines (86 loc) · 4.79 KB
/
AsyncMonkeyEngine.cs
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
using System;
using System.Threading;
using System.Threading.Tasks;
using Polly.Contrib.Simmy.Utilities;
namespace Polly.Contrib.Simmy
{
internal static class AsyncMonkeyEngine
{
private static async Task<bool> ShouldInjectAsync(
Context context,
CancellationToken cancellationToken,
Func<Context, CancellationToken, Task<double>> injectionRate,
Func<Context, CancellationToken, Task<bool>> enabled,
bool continueOnCapturedContext)
{
// to prevent execute config delegates if token is signaled before to start.
cancellationToken.ThrowIfCancellationRequested();
if (!await enabled(context, cancellationToken).ConfigureAwait(continueOnCapturedContext))
{
return false;
}
// to prevent execute injectionRate config delegate if token is signaled on enable configuration delegate.
cancellationToken.ThrowIfCancellationRequested();
double injectionThreshold = await injectionRate(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
// to prevent execute further config delegates if token is signaled on injectionRate configuration delegate.
cancellationToken.ThrowIfCancellationRequested();
injectionThreshold.EnsureInjectionThreshold();
return ThreadSafeRandom_LockOncePerThread.NextDouble() < injectionThreshold;
}
internal static async Task<TResult> InjectBehaviourImplementationAsync<TResult>(
Func<Context, CancellationToken, Task<TResult>> action,
Context context,
CancellationToken cancellationToken,
Func<Context, CancellationToken, Task> injectedBehaviour,
Func<Context, CancellationToken, Task<Double>> injectionRate,
Func<Context, CancellationToken, Task<bool>> enabled,
bool continueOnCapturedContext)
{
if (await ShouldInjectAsync(context, cancellationToken, injectionRate, enabled, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext))
{
await injectedBehaviour(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}
// to prevent execute the user's action if token is signaled on injectedBehaviour delegate.
cancellationToken.ThrowIfCancellationRequested();
return await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}
internal static async Task<TResult> InjectExceptionImplementationAsync<TResult>(
Func<Context, CancellationToken, Task<TResult>> action,
Context context,
CancellationToken cancellationToken,
Func<Context, CancellationToken, Task<Exception>> injectedException,
Func<Context, CancellationToken, Task<Double>> injectionRate,
Func<Context, CancellationToken, Task<bool>> enabled,
bool continueOnCapturedContext)
{
if (await ShouldInjectAsync(context, cancellationToken, injectionRate, enabled, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext))
{
Exception exception = await injectedException(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
// to prevent throws the exception if token is signaled on injectedException configuration delegate.
cancellationToken.ThrowIfCancellationRequested();
if (exception != null)
{
throw exception;
}
}
return await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}
internal static async Task<TResult> InjectResultImplementationAsync<TResult>(
Func<Context, CancellationToken, Task<TResult>> action,
Context context,
CancellationToken cancellationToken,
Func<Context, CancellationToken, Task<TResult>> injectedResult,
Func<Context, CancellationToken, Task<Double>> injectionRate,
Func<Context, CancellationToken, Task<bool>> enabled,
bool continueOnCapturedContext)
{
if (await ShouldInjectAsync(context, cancellationToken, injectionRate, enabled, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext))
{
return await injectedResult(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}
// to prevent inject the result if token is signaled on injectedResult delegate.
cancellationToken.ThrowIfCancellationRequested();
return await action(context, cancellationToken).ConfigureAwait(continueOnCapturedContext);
}
}
}