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

[queued-request-controller] Batch RPC requests #3781

Merged
merged 14 commits into from
Mar 8, 2024
Merged

Conversation

Gudahtt
Copy link
Member

@Gudahtt Gudahtt commented Jan 12, 2024

Explanation

The QueuedRequestController will now batch RPC requests by origin. Each batch of requests will be processed in parallel, allowing existing features relating to groups of requests to function correctly with queuing enabled (e.g. the confirmation navigation buttons, and the "Reject all" button). The batching by origin also ensures that confirmations from different dapps are never displayed together in a group, which will help prevent users from confusing which dapp each confirmation is from.

The meaning of queuedRequestCount has changed; it now represents the total number of queued requests, i.e. those that are queued but are not being processed. Previously it included processing requests as well. Given that the number of confirmations awaiting approval is already tracked elsewhere, it was not useful to double count them by including them in the queued request count as well.

Additionally, when the QueuedRequestController requires the globally selected network to be changed, we now emit an event rather than triggering a confirmation. This aligns with recent designs for this use case.

The actions NetworkController:getNetworkConfigurationByNetworkClientId and ApprovalController:addRequest were only used for triggering the switch network confirmation, so they are no longer needed now. They have been removed. This removes the last dependency of this controller on the ApprovalController, so it has been removed as a dependency as well.

References

Closes #3763
Fixes #3967
Closes #3983

Changelog

@metamask/queued-request-controller

Changed

  • BREAKING: The QueuedRequestController will now batch queued requests by origin
    • All of the requests in a single batch will be processed in parallel.
    • Requests get processed in order of insertion, even across origins/batches.
    • All requests get processed even in the event of preceding requests failing.
  • BREAKING: The queuedRequestCount state no longer includes requests that are currently being processed. It just counts requests that are queued.
  • BREAKING: The QueuedRequestController no longer triggers a confirmation when a network switch is needed
    • The network switch now happens automatically, with no confirmation.
    • A new QueuedRequestController:networkSwitched event has been added to communicate when this has happened.
    • The QueuedRequestController messenger no longer needs access to the actions NetworkController:getNetworkConfigurationByNetworkClientId and ApprovalController:addRequest.
    • The package @metamask/approval-controller has been completely removed as a dependency

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've highlighted breaking changes using the "BREAKING" category above as appropriate

@Gudahtt

This comment was marked as outdated.

This comment was marked as outdated.

@Gudahtt

This comment was marked as outdated.

This comment was marked as outdated.

@Gudahtt Gudahtt force-pushed the batch-queued-requests branch 3 times, most recently from c131a7d to d392f46 Compare January 31, 2024 22:03
@Gudahtt

This comment was marked as outdated.

This comment was marked as outdated.

@Gudahtt Gudahtt force-pushed the batch-queued-requests branch 2 times, most recently from 3499494 to 83a88a4 Compare February 8, 2024 01:17
@Gudahtt

This comment was marked as outdated.

This comment was marked as outdated.

@Gudahtt Gudahtt force-pushed the batch-queued-requests branch 2 times, most recently from 60ceb9e to b9f6d86 Compare February 14, 2024 04:53
@Gudahtt

This comment was marked as outdated.

This comment was marked as outdated.

@Gudahtt Gudahtt force-pushed the batch-queued-requests branch 2 times, most recently from 8be3d5c to 0114356 Compare February 16, 2024 14:03
@Gudahtt Gudahtt changed the base branch from main to refactor-queued-request-processing February 26, 2024 22:48
@Gudahtt Gudahtt force-pushed the batch-queued-requests branch 6 times, most recently from 493b6a8 to c52ac3a Compare February 27, 2024 00:03
// Use an array to track the order of execution
const executionOrder: string[] = [];
// resolve and await requests in the wrong order
// If requests were executed one-at-a-time, this would deadlock
Copy link
Contributor

Choose a reason for hiding this comment

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

I love it when I learn things as I'm reading tests!

The `QueuedRequestController` will now batch RPC requests by origin.
Each batch of requests will be processed in parallel, allowing existing
features relating to groups of requests to function correctly with
queuing enabled (e.g. the confirmation navigation buttons, and the
"Reject all" button). The batching by origin also ensures that
confirmations from different dapps are never displayed together in a
group, which will help prevent users from confusing which dapp each
confirmation is from.

The meaning of `queuedRequestCount` has changed; it now represents the
total number of queued requests, i.e. those that are queued but are
**not** being processed. Previously it included processing requests as
well. Given that the number of confirmations awaiting approval is
already tracked elsewhere, it was not useful to double count them by
including them in the queued request count as well.

Closes #3763
…nt (#3987)

## Explanation

When the `QueuedRequestController` requires the globally selected
network to be changed, we now emit an event rather than triggering a
confirmation. This aligns with recent designs for this use case.

The actions `NetworkController:getNetworkConfigurationByNetworkClientId`
and `ApprovalController:addRequest` were only used for triggering the
switch network confirmation, so they are no longer needed now. They have
been removed. This removes the last dependency of this controller on the
`ApprovalController`, so it has been removed as a dependency as well.

## References

Closes #3983

## Changelog

### `@metamask/package-a`

#### Changed
- **BREAKING:** The `QueuedRequestController` no longer triggers a
confirmation when a network switch is needed
  - The network switch now happens automatically, with no confirmation.
- A new `QueuedRequestController:networkSwitched` event has been added
to communicate when this has happened.
- The `QueuedRequestController` messenger no longer needs access to the
actions `NetworkController:getNetworkConfigurationByNetworkClientId` and
`ApprovalController:addRequest`.
- The package `@metamask/approval-controller` has been completely
removed as a dependency

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
mcmire
mcmire previously approved these changes Mar 5, 2024
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

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

I've reviewed the logic again and it makes sense to me. I've also reviewed the associated tickets and it seems like this PR addresses them well.

* origin/main:
  refactor(controller-utils): replace `any` with types for type safety (#3975)
  Release 123.0.0 (#4007)
  [token-detection-controller] Refactor `detectTokens` method (#3938)
  fix: update usage of OP goerli to OP Sepolia (#3999)
@Gudahtt
Copy link
Member Author

Gudahtt commented Mar 5, 2024

Just merged in main to resolve conflcits (the ApprovalController version was bumped, but this PRs removes it as a dependency)

).rejects.toThrow('Request failed');
expect(controller.state.queuedRequestCount).toBe(0);
});

it('handles errors without interrupting the execution of the next item in the queue', async () => {
it('correctly processes the next item in the queue', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be worth clarifying this behavior in changelog/description. AIUI, requests can fail intermittently (e.g. intermittent network error persisting beyond any retries in the lower level but resolving on subsequent requests in the queue) so this can be taken as in conflict with "Request order is still strictly maintained" (which could imply that later items should not be attempted in case the first item fails). Maybe something like:

Items get processed in order of insertion. All items get processed even in the event of preceding items failing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm. I do like your description better, but I don't see the conflict with "Request order is strictly maintained".

Oh, well I guess if request order includes the response, I can see the conflict. It's just the start of processing that is ordered. I'll clarify.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have updated the PR description change entries and made some clarifications here: 6c159f1

Gudahtt and others added 3 commits March 6, 2024 12:09
Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
@jiexi
Copy link
Contributor

jiexi commented Mar 7, 2024

I have nothing to add since my last set of comments. LGTM, but will defer to others for second sign off.

Copy link
Contributor

@adonesky1 adonesky1 left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks for this @Gudahtt! Code looks great and I've tested it and its fixing some bugs I'd been seeing previously!

Copy link
Contributor

@cryptodev-2s cryptodev-2s left a comment

Choose a reason for hiding this comment

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

LGTM!

Copy link
Contributor

@BelfordZ BelfordZ left a comment

Choose a reason for hiding this comment

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

some great improvements made here, batching, no confirms for the switching, all great stuff. shippppitttt

} else {
// Process request immediately
// Requires switching network now if necessary
await this.#switchNetworkIfNecessary();
Copy link
Contributor

@BelfordZ BelfordZ Mar 7, 2024

Choose a reason for hiding this comment

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

eth_requestAccounts has a confirmation only the first time its called from a dapp. It also does not really require network switching to occur beforehand. This causes the slightly odd behaviour of calling eth_requestAccounts causing the network to switch but there was never a confirmation dialog that popped up. In this case, it is unclear to the user why the network has changed.

Anyways, this should do it:

Suggested change
await this.#switchNetworkIfNecessary();
if (request.method !== 'eth_requestAccounts') {
await this.#switchNetworkIfNecessary();
}

Copy link
Contributor

@BelfordZ BelfordZ Mar 8, 2024

Choose a reason for hiding this comment

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

Just thought I'd mention that I think its Ok to move forward with or without this suggested fix. The effects are very subtle and I doubt anyone will notice for a while, if at all, so we could revisit this later if you see fit (or decide that switching network before handling eth_requestAccounts makes sense, and thus not revisit this).

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for pointing this out, I don't fully understand the issue but I'll look into it further!

Copy link
Member Author

Choose a reason for hiding this comment

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

OK I see what you mean now, great catch! Agreed that this is a good solution

@Gudahtt Gudahtt merged commit 8d74b81 into main Mar 8, 2024
139 checks passed
@Gudahtt Gudahtt deleted the batch-queued-requests branch March 8, 2024 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
9 participants