-
Notifications
You must be signed in to change notification settings - Fork 450
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
⚡️ Cache latest op version when broadcasting presence #679
Conversation
788b18f
to
e247940
Compare
389e06e
to
5c9994d
Compare
At the moment, when sending a presence update to other subscribers, we [call `transformPresenceToLatestVersion()`][1] for every presence update which internally [calls `getOps()`][2] for every presence update. Calls to `getOps()` can be expensive, and rapid presence updates may cause undue load on the server, even when the `Doc` has not been updated. This change tries to mitigate this by subscribing to a pubsub stream for any `Doc`s that an `Agent` tries to broadcast presence on. We keep an in-memory cache of the latest snapshot version sent over this stream, which lets us quickly check if a presence broadcast is already current without needing to query the database at all. To avoid leaking streams, the `Agent` will internally handle its stream subscription state by: - subscribing whenever a non-`null` presence update is broadcast - unsubscribing whenever a `null` presence update is broadcast This means that rapid changes in presence being `null` or not can still result in database calls, but even in this case they should be less bad than before, because we only perform a snapshot fetch instead of ops. [1]: https://github.com/share/sharedb/blob/297ce5dc66563a5955311793a475768d73ac8b87/lib/agent.js#L804 [2]: https://github.com/share/sharedb/blob/297ce5dc66563a5955311793a475768d73ac8b87/lib/backend.js#L919
5c9994d
to
87ef11d
Compare
}; | ||
|
||
Agent.prototype._unsubscribeDocVersion = function(collection, id, callback) { | ||
var stream = util.dig(this.latestDocVersionStreams, collection, id); |
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.
This doesn't clean up the this.latestDocVersions
, which means a long-lived client that goes through many docs could have an agent with tons of old entries in that map.
Per discussion, immediately cleaning up this.latestDocVersions
may make the case of multiple null presences worse. Perhaps a delayed cleanup or something.
- Clean up `latestDocVersions` when unsubscribing - Fix not setting version if the object already exists - Removes `null` presence check, which won't work if the object has been destroyed
At the moment, when sending a presence update to other subscribers, we call
transformPresenceToLatestVersion()
for every presence update which internally callsgetOps()
for every presence update.Calls to
getOps()
can be expensive, and rapid presence updates may cause undue load on the server, even when theDoc
has not been updated.This change tries to mitigate this by subscribing to a pubsub stream for any
Doc
s that anAgent
tries to broadcast presence on. We keep an in-memory cache of the latest snapshot version sent over this stream, which lets us quickly check if a presence broadcast is already current without needing to query the database at all.To avoid leaking streams, the
Agent
will internally handle its stream subscription state by:null
presence update is broadcastnull
presence update is broadcastThis means that rapid changes in presence being
null
or not can still result in database calls, but even in this case they should be less bad than before, because we only perform a snapshot fetch instead of ops.