Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The previous version of this code could sometimes provide a non-positive interval for Ticker.Reset, which causes it to panic. This could happen if a job was already overdue to run when
timeUntilNextRun()
was called, or as time progressed throughout its execution.There are two fixes here:
timeUntilNextRun()
, only evaluate the current time once and use that throughout so we can be sure we're not skipping safety checks.PeriodicJobEnqueuer
loop to use atime.Timer
instead of atime.Ticker
since we intend to reset it on every iteration anyway.Step (2) was tricky as it always is when reusing
time.Timer
in Go [1] thanks to its poor design, but I believe I've done that in a safe way here. The reusable timer is now created with 0 duration, ensuring that it will fire quickly, and then the next line always blocks until it fires. This introduces a minimal delay, but it's done to ensure that the first part of the loop (resetting the timer) can always succeed without needing to first try to stop the timer. The only other way the loop can repeat is if we've just received from the timer, so we are guaranteed to be able to safely reset it here.