Skip to content
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

Dealing with a canceled Context #8

Merged
merged 4 commits into from
Jan 8, 2022

Conversation

Deleplace
Copy link
Contributor

Hi Seth, I spotted a small bug with a straightforward fix so I'm taking the liberty to make a PR without creating an issue first.

Current behaviour

  • NewConstant rejects a duration of 0
  • It is however possible that a Backoff.Next() returns a duration of 0, e.g. when using WithJitter
  • Do executes the user func at least once, even if the provided Context is already canceled

Problems

  • When the backoff duration is 0, it is possible that the user func gets retried, bypassing the Context cancelation check. This is because Go's select statement doesn't let us specify case priority, when several cases are ready to proceed.
  • It seems to me that, when the provided Context is already canceled, Do should not execute the user func at all.

Fix

  • Test ctx.Done() alone, before the select with 2 cases.
  • Test ctx.Done() before the very first call to the user func.

For readability, please find 3 commits. The 1st commit is a test that usually fails, before the code fix.

Copy link
Owner

@sethvargo sethvargo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM, but can you move the test into an existing test file (maybe retry_test.go)?

@@ -66,6 +73,13 @@ func Do(ctx context.Context, b Backoff, f RetryFunc) error {
return rerr.Unwrap()
}

// ctx.Done() has priority, so we test it alone first
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If only Go had a priority for select...

@sethvargo
Copy link
Owner

It is however possible that a Backoff.Next() returns a duration of 0, e.g. when using WithJitter

Can you tell me more about this?

@Deleplace
Copy link
Contributor Author

WithJitter may produce a duration 0 when the magnitude of the jitter exceeds the duration of the "next backoff": val = 0

This case does not produce a hot loop though, because statistically there is more delay added by positive jitter, than subtracted by negative jitter.

@Deleplace
Copy link
Contributor Author

Test moved to retry_test.go

@sethvargo sethvargo merged commit 2b17a41 into sethvargo:main Jan 8, 2022
@github-actions
Copy link

This pull request has been automatically locked since there has not
been any recent activity after it was closed. Please open a new
issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants