feat(zero-client): client-side query flight control #5385
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
When using a "self-fetching components" pattern where each component fetches its own data via Zero, a page load can trigger 100-150+ queries simultaneously. These all get batched and sent to the server in one
changeDesiredQueriesmessage, which overwhelms the view-syncer.How queries back up on the server
The view-syncer processes queries sequentially per clientGroupID due to a lock:
When the client sends 150 queries in one message, they all get processed under one lock acquisition:
Our Workaround
This PR sends queries in separate messages so the server acquires/releases the lock for each:
By making sure some queries yield we're making sure that the lock isn't held completely.
Not Intended to Merge
This PR is a hacky client-side workaround, not intended for merging. But... what's the best way to prevent the view-syncer from blocking on large query batches?
Some options (not in any particular order):
Server responds incrementally. Instead of waiting until all queries are processed, send data back query-by-query as each one completes. This could look jank, but works for our use case!
Server-side timeout or "good enough" threshold. After N queries or M seconds, yield data before continuing. Even if it means queries take longer overall.