-
-
Notifications
You must be signed in to change notification settings - Fork 186
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
Added polling-controller #1703
Added polling-controller #1703
Conversation
3bce199
to
db9ec11
Compare
No top level dependency changes detected. Learn more about Socket for GitHub ↗︎ |
28cb1e8
to
28de47f
Compare
A few small nits but otherwise lets gooo |
if (this.intervalIds[networkClientId]) { | ||
clearTimeout(this.intervalIds[networkClientId]); | ||
delete this.intervalIds[networkClientId]; | ||
} |
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.
i think this logic should be DRY'ed into it's own private method since we use it in the stop()
method as well
} | ||
let found = false; | ||
this.networkClientIdTokensMap.forEach((tokens, networkClientId) => { | ||
if (tokens.has(pollingToken)) { |
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.
nit. feel free to ignore. I feel that this would be slightly cleaner if this was turned negated / turned into a guard.
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 great!
On second thought, it does seem important for the interval to be configurable
* @param networkClientId - The networkClientId to start polling for | ||
* @returns void | ||
*/ | ||
start(networkClientId: NetworkClientId) { |
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.
Should we support polling controllers which may only have 1 polling loop active per networkClientId? Perhaps we could have an option passed into the constructor to indicate this? for example, if the blocktracker was a controller, we would only want to have 1 active block polling per network.
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.
Good question. I can't think of any controllers where we'd want this offhand though.
/** | ||
* Stops polling for all networkClientIds | ||
*/ | ||
stopAll() { |
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.
Should we have this optionally take a networkClientId, allowing all polling to be stopped for a given network?
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.
We could do this but I'm not sure I can think of a situation where we'd want this behavior. In general PollingTokens should be disconnected individually so we can be sure that there are no lingering listeners depending on active polling. TBH I'm not even sure where we'll want to call stopAll?
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.
stopAll
is useful in tests but I don't think many other places will call it
try { | ||
await this.executePoll(networkClientId); | ||
} catch (error) { | ||
console.error(error); |
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.
Should we be eating the errors? I suppose even if we let the error bubble up, since this is happening inside an interval, nothing else would be able to catch the error anyways. In this case, does it make sense to add an interface to subscribe to errors? IE how would a controller using this abstract controller be able to detect an error in its executePoll call, and react to it.
Should we keep polling when there are errors? Maybe we can have an option to configure an linear/exponential backoff when there are errors.
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.
I had the same thought, this is definitely not ideal for error handling. But it's strictly better than the status quo, where typically the error is completely swallowed and not even logged. Something to consider later as an enhancement perhaps
Co-authored-by: Alex Donesky <adonesky@gmail.com>
bb2371e
to
911ff20
Compare
} from '@metamask/base-controller'; | ||
import type { NetworkClientId } from '@metamask/network-controller'; | ||
import type { Json } from '@metamask/utils'; | ||
import { v1 as random } from 'uuid'; |
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.
Hmm, why not use v4? It's my understanding that v1 is not quite as random, and that v4 is the better choice in most situations
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.
LGTM! Just one pending suggestion
👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎ This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored. |
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.
LGTM!
Unused dependencies have been removed
## Explanation > Originally was in #1673 but pulled out to get this in on its own. Adds an abstract class (currently named `PollingController`. The start and stop methods are parameterized by `networkClientId`'s and `pollingToken`'s and polling intervals are stored in class variables by `chainId` so that multiple `networkClients`/`chainIds` can poll simultaneously. `executePoll` is an abstract method to be implemented by the controller itself so that this pattern could be generalized and be agnostic to what is being executed on the polling interval. ## References Related to #1673 Related to MetaMask/MetaMask-planning#1314 --------- Co-authored-by: Alex Donesky <adonesky@gmail.com>
## Explanation > Originally was in #1673 but pulled out to get this in on its own. Adds an abstract class (currently named `PollingController`. The start and stop methods are parameterized by `networkClientId`'s and `pollingToken`'s and polling intervals are stored in class variables by `chainId` so that multiple `networkClients`/`chainIds` can poll simultaneously. `executePoll` is an abstract method to be implemented by the controller itself so that this pattern could be generalized and be agnostic to what is being executed on the polling interval. ## References Related to #1673 Related to MetaMask/MetaMask-planning#1314 --------- Co-authored-by: Alex Donesky <adonesky@gmail.com>
Explanation
Adds an abstract class (currently named
PollingController
. The start and stop methods are parameterized bynetworkClientId
's andpollingToken
's and polling intervals are stored in class variables bychainId
so that multiplenetworkClients
/chainIds
can poll simultaneously.executePoll
is an abstract method to be implemented by the controller itself so that this pattern could be generalized and be agnostic to what is being executed on the polling interval.References
Related to #1673
Related to https://github.com/MetaMask/MetaMask-planning/issues/1314