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

PollingController: add option to poll by blockTracker #3623

Closed
wants to merge 9 commits into from

Conversation

adonesky1
Copy link
Contributor

@adonesky1 adonesky1 commented Dec 6, 2023

Addresses: https://github.com/MetaMask/MetaMask-planning/issues/1788

@matthewwalsh0 and the Confirmation Systems Team is hoping to use the PollingController for a new UserOperationController but are needing to tie polling intervals to block times rather than a static interval length. This is achievable using the vanilla blockTracker and adding callbacks to its listeners but we will want to multiplex it for multichain and it so it makes sense to do so using the PollingController abstraction since they are basically doing the same thing but just using a different source for the interval of execution.

@adonesky1 adonesky1 force-pushed the add-block-tracker-polling branch 4 times, most recently from 4d19a0b to 04526f2 Compare December 6, 2023 22:58
@adonesky1 adonesky1 marked this pull request as ready for review December 6, 2023 23:11
@adonesky1 adonesky1 requested a review from a team as a code owner December 6, 2023 23:11
@jiexi
Copy link
Contributor

jiexi commented Dec 7, 2023

It's almost like we need another abstraction that handles just the idea of polling tokens, starting, and stopping. And two implementations of that for Polling by setTimeout and polling by subscription with listener

@adonesky1
Copy link
Contributor Author

adonesky1 commented Dec 7, 2023

It's almost like we need another abstraction that handles just the idea of polling tokens, starting, and stopping. And two implementations of that for Polling by setTimeout and polling by subscription with listener

I agree this would be a more elegant solution. Not sure if we need this to be flexible to more ways of polling. All a question of time and effort imo.

networkClientId,
options,
);
blockTracker.addListener('latest', updateOnNewBlock);
Copy link
Member

Choose a reason for hiding this comment

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

As discussed, do we want a mutex here to ensure executions don't overlap if you have slow asynchronous work inside _executePoll?

Or alternatively we could chain blockTracker.once but that may risk missing blocks which could be undesirable.

Or alternatively, we could put the burden of a mutex on the child controller inside their _executePoll?

}

setPollWithBlockTracker(
getNetworkClientById: (networkClientId: NetworkClientId) => NetworkClient,
Copy link
Member

@matthewwalsh0 matthewwalsh0 Dec 7, 2023

Choose a reason for hiding this comment

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

I wasn't sure if this argument would be best as a ControllerMessenger as this (Network)PollingController can know how to get a network client given an ID, plus it encourages messenger adoption and avoids each child controller having to define this function by binding it to their messenger for example.

But I suppose the counter-argument is that it would require all child controllers to be BaseController2 or have a messenger.

clearTimeout(this.#intervalIds[key]);
delete this.#intervalIds[key];
// if applicable stop polling on a static interval
if (this.#intervalIds[key]) {
Copy link
Member

Choose a reason for hiding this comment

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

Very minor, but for the sake of the size of this method, I wonder if it's worth moving each of these blocks to private methods like removeExistingTimeout and removeExistingListener?

@mcmire
Copy link
Contributor

mcmire commented Dec 7, 2023

I agree with @jiexi. I am hesitant accepting this as I am a bit uncomfortable with mashing two styles of polling into one controller. I don't think this extends the API in an intuitive way, and it makes the code more difficult to comprehend. Since there is no state in PollingController, it feels like this would be a perfect opportunity to refactor the existing code to create "poller" objects and make use of the strategy pattern to select which one to use at runtime.

Is there any other solution that the Confirmation Systems can use in the meantime?

@adonesky1
Copy link
Contributor Author

adonesky1 commented Dec 7, 2023

@mcmire @jiexi took a rough pass at using the approach you recommended: #3636

Wanted some feedback before proceeding further. Let me know what you think.

adonesky1 added a commit that referenced this pull request Dec 12, 2023
Ready for review: **I will add changelog entries when/if we decide to
roll with this approach.**

Alternative approach to refactoring the PollingController per this
[feedback](#3623 (comment))
on [PollingTracker enhancement
work](#3623)
@adonesky1
Copy link
Contributor Author

Superceded by #3636

@adonesky1 adonesky1 closed this Dec 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants