-
Notifications
You must be signed in to change notification settings - Fork 58
WebSocket keepalive changes #648
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
Conversation
🦋 Changeset detectedLatest commit: 430f99f The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
360b135
to
a31ddb5
Compare
…ync-js into websocket-keepalives
packages/react-native/src/sync/bucket/ReactNativeBucketStorageAdapter.ts
Show resolved
Hide resolved
packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts
Show resolved
Hide resolved
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.
The changes here look good to me. Happy from my side :)
Background
RSocket handles keepalive as follows:
keepAlive
ms (20s).lifetime
ms (30s).That gives a 10s grace period between sending and receiving the message.
The issue here comes in when there is either:
Either of the above could block the keepalive response for more than that 10s, resulting in
Error: Closed. Original cause [Error: No keep-alive acks for 30000 millis].
.One workaround was added in #494, reducing the number of messages that are requested by the client at a time. However, this can decrease throughput.
Keepalive Changes
This implements an additional workaround that:
lifetime
to 90s.This applies per-message, not per-byte or per-frame. This means we can still get a timeout error if a single message takes more than 10s to send over the connection. Our messages are generally limited to 1MB in size (unless a single operation is larger than that), so it should cover most cases.
BSON parsing changes
This now delays parsing of BSON data until the line is processed, rather than when it is received. This helps since:
The Rust implementation takes this further to move the BSON parsing into the SQLite extension, which helps even more.
This refactors the DataStream handling a bit to support this. This also fixes some type issues we had, such as mixing up Uint8Array and ArrayBuffer.
Future options
Testing
NodeJS
Did regression testing on NodeJS using all 4 combinations of
connectionMethod
andclientImplementation
- no issues found.React Native
On React-Native, tested using websockets only, for both
clientImplementation
methods.For the JavaScript implementation, overall sync performance appears to be slightly better now, but I didn't do proper benchmarking.Before, data would typically be processed batches of 10x deserialize, then 10x saveSyncData, alternating between them. Now, one message is deserialized at a time.
For op-sqlite, I used react-native-barebones-opsqlite. I had trouble with the fetch implementation - both write checkpoints and http streams get
Value is undefined, expected a String
(see facebook/react-native#27741 (comment)). But websockets do work with both the JS and Rust implementations.Web
Tested using the diagnostics app, using all 4 combinations of
connectionMethod
andclientImplementation
- no issues found.TODO