share / sharedb

Realtime database backend based on Operational Transformation (OT)
Other
6.27k stars 451 forks source link

increase delay before flush from client? #185

Open ianstormtaylor opened 7 years ago

ianstormtaylor commented 7 years ago

Hey!

I'm learning the codebase, and I was wondering... right now the flush method on the client is called on process.nextTick, which adds a small delay, so that multiple synchronous operations can be composed together before being sent to the server.

Is there any harm in increasing this delay? For example what if it was 100ms instead? I'm thinking for the case of someone typing in a rich text editor—that slightly longer delay might 2–5x the composition rate when someone is typing quickly (or backspacing quickly).

Anyone know if this is viable?

gkubisa commented 6 years ago

I think that the lack of a longer delay is not a problem in practice because at most one operation can be "in-flight" at a time. So, if someone is typing/deleting characters quickly, the first change would be sent to the servers immediately (process.nextTick) but all following changes would be composed until the first operation is acknowledged by the server. This creates a kind of a natural debounce mechanism with the delay tied to the latency of round-tripping operations to the server.

brainkim commented 6 years ago

I’ve learned that you can’t buffer or store operations outside of the ShareDB client b/c operations need to be transformed against incoming edits. However, ShareDB documents have undocumented pause and resume methods which I’ve been using to throttle clients (don’t need ops sent with millisecond precision). You can pause the document when you create it and then call resume when you want to save the current document. I have a throttled method on a helper class that looks like this:

  save = throttle(
    () => {
      if (this.shareDoc) {
        this.shareDoc.resume();
        this.shareDoc.pause();
        this.connection.whenNothingPending(this._nothingPending);
      }
    },
    5000,
    { leading: false, trailing: true },
  );

I call save whenever stuff happens and let the throttle function deal with buffering/sending ops to the server. This has been working for me so far but who knows 🤷‍♂️