-
Notifications
You must be signed in to change notification settings - Fork 25
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
Makes cancellable configuration-providing delegates #41
Conversation
…ctors the engine to add some validations to avoid execute extra code when cancellation token is signaled.
Thanks @vany0114 , these are great questions! I will try to dive in and have a look over the weekend/coming days! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀 looking very nice to me, @vany0114 ! Will contribute thoughts separately on questions in your cover note.
{ | ||
if (!await enabled(context).ConfigureAwait(continueOnCapturedContext)) | ||
// to prevent execute config delegates if user cancels the whole execution before to start. | ||
cancellationToken.ThrowIfCancellationRequested(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Perfect for a policy engine to test for cancellation as the first thing it does. This is a typical pattern for Polly policies.
It matches the approach of the .NET base class libraries: for example Task.Run(...)
makes a cancellation check before running the passed delegate.
{ | ||
return false; | ||
} | ||
|
||
double injectionThreshold = await injectionRate(context).ConfigureAwait(continueOnCapturedContext); | ||
// to prevent execute injectionRate config delegate if user cancels execution on enable configuration delegate. | ||
cancellationToken.ThrowIfCancellationRequested(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to check for cancellation again here (in case the CancellationToken
has been signalled, but the user's enabled
delegate didn't check it, so didn't honor cancellation).
Note: the good reason for checking cancellation here is that a timing-out CancellationToken
might have been provided (for example from a TimeoutPolicy
), and it is possible the user's enabled
delegate didn't honor it.
(I am not thinking so much that the user would have signal the CancellationToken
within the enabled
delegate. If the user wants the chaos not to go ahead, they can simply return false
from that delegate.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, I think that's gonna cover cancellation for timing out just in case the user wrap chaos policies with a timeout policy, which would be highly likely.
double injectionThreshold = await injectionRate(context, cancellationToken).ConfigureAwait(continueOnCapturedContext); | ||
|
||
// to prevent execute further config delegates if user cancels execution on injectionRate configuration delegate. | ||
cancellationToken.ThrowIfCancellationRequested(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to check for cancellation again here (for same reason as a few lines above)
{ | ||
Func<Context, CancellationToken, Task<bool>> enabled = (ctx, ct) => | ||
{ | ||
cts.Cancel(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me! I expect, if the user wanted to choose not to introduce the chaos, they could just return false
from this delegate. But the cts.Cancel()
here is a good simulation of something else (eg a TimeoutPolicy) signalling the CancellationToken
some time during the execution of the enabled
delegate.
(Similarly for all the other tests.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, I think is very unlikely that a user does something like that explicitly to cancel the chaos injection, I just wanted to show how would be the behavior of cancellation when the token is signaled, usually (as you said) from a timeout policy. Maybe I should rename the test cases to be clearer 😅
Hey @vany0114
👍
Looks good to me! Per my comments in detailed review, a good reason for checking for cancellation frequently can be because something independent (some other thread; a timeout timer) has signalled the
I think it is fine for a Policy to enforce cancellation even if the user code doesn't. Polly policies do this. You are right that we should make the sync policies do the same. After that, you can decide whether you want to make a v0.2 release with this straight away 🚀 , or if there is anything else you want to add/change for a v0.2. I can talk you through the process we normally use (for Polly) when we make a new release! |
Hey @reisenberger Thanks for taking a look and your thoughts. Yeah, I'm gonna do the change for sync policies as well and also implement #20 since it's related too. After that, I can make a v0.2 release. And yes, I'd love to know how you guys handle the release process on Polly to apply it on Simmy as well! |
Sync policies are done already. I've updated the PR. |
@reisenberger I updated the overloads which were taking the
Context
in configuration-providing delegates instead of adding new overloads (breaking change), basically to avoid the proliferation of the overloads as we discussed it previously, but it might be solved with the new syntax tho.I added some validations on
AsyncMonkeyEngine
(not sure if that is correct) in order to avoid to execute extra code when the cancellation token is signaled at different times during the execution.enable
configuration delegateinjectionRate
configuration delegateinjectedBehaviour
delegate (This is not a configuration delegate but the user might want to cancel the original action after to inject a custom behavior)injectedException
configuration delegateI also changed the
AsyncInjectLatencyPolicy
(1, 2) in order to make the latency configuration delegate cancellable because it was injecting the latency even though you signal the cancellation from that configuration delegate.However, after this refactor I have a big doubt: should we let the cancellation token request flow to the user rather than let Simmy does it using
ThrowIfCancellationRequested()
onAsyncMonkeyEngine
? if not, I'll need to update theMonkeyEngine
as well (to put those validations).Or just validate once on
ShouldInjectAsync
method at the beginning? and let the user does something like this:Thoughts?
ref #19