This repository was archived by the owner on Oct 16, 2025. It is now read-only.
Prevent multiple simultaneous polling loops#208
Merged
matthewwalsh0 merged 2 commits intomainfrom Feb 6, 2024
Merged
Conversation
Replace loop with timeout chain. Update unit tests. Remove unnecessary async keywords.
legobeat
reviewed
Jan 23, 2024
dbrans
previously approved these changes
Jan 24, 2024
mcmire
approved these changes
Feb 2, 2024
Contributor
mcmire
left a comment
There was a problem hiding this comment.
Good work investigating this! This makes sense to me. I just had a couple of questions but they are non-blocking.
Contributor
|
@matthewwalsh0 I think we can ship this? :) |
This was referenced May 23, 2024
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Problem
The central mechanism of the
PollingBlockTrackeris thesynchronizemethod which provides a loop to fetch the block number then wait for a given interval, all until the block tracker is no longer running meaning it no longer has any event listeners.If all listeners are removed while the
synchronizeloop is waiting for the timeout, once the timeout finishes the loop will exit sinceisRunningwill now befalse.If all listeners are removed but then some are added again, all while waiting for a timeout, this allows a new synchronise loop to be created since
isRunningwasfalsemeaning_maybeStart>_start>_synchronize. Once the original timeout finishes however, it continues as normal sinceisRunningistrueagain meaning we now have two synchronize loops occurring simultaneously with different interval alignment meaning we ultimately poll more often than the desired polling interval. This problem can stack and create many simultaneous loops thereby greatly increasing the actual polling interval.Test Steps
Solution
There are multiple possible solutions but for the sake of the simplest final code, this PR replaces the
synchronizeloop with asetTimeoutchain.This allows duplicate "loops" to be easily avoided since we can simply clear any pending timeouts before creating a new one, plus do the same when all listeners are removed and the
_endmethod is ultimately called.In addition, we can simplify the
_maybeStart,_maybeEnd,_start, and_endmethods by removing theasynckeyword since no asynchronous logic is required. This introduces additional clarity in code path since we are invoking these methods from synchronous event listeners meaning it is ideal that we only require synchronous methods.Note that
updateAndQueueis anasyncmethod but we don't need toawaitthis since we want to emit the_startedevent before the first iteration has been completed, and it includes its own error handling.