How to handle edge case with collab module

The result of today’s test: while they discovered some oddities about Fidus Writer in general, they were not able to crash the editor. A second team was giving it a go, but they weren’t able to break it either. So beyond known issues, we seem to be relatively fine.

Nice, that’s great to here!

The new protocol has a pitfall of its own – it’s not hard to work around, but it’s awkward. If you have multiple changes being made in quick succession, the client will send the first one to the server, but won’t assume it arrived there. It might then, before it gets its changes back from the server, try to send again. At that point, its confirmed version is still the old one, so it’ll try to send all steps, including the previously sent ones, leading to a conflict. Conflicts should be responded to by fetching new changes anyway, so if you put everything together correctly, the end result should still be fine, but you do get a bunch of unnecessary requests happening.

To avoid these, we could bring back a redundant confirmation response to submitting new changes, which the client can use, but which, through the adjustments made in response to this issue, it doesn’t need to rely on. But I’m not sure I want to add more complexity. @kiejo Did you run into this issue? If so, how did you solve it?

The way I solved it: have the server still create confirmation messages, but just use the receive function to confirm them with pm. Also, when a change has been sent to the server, don’t send another change until either A) the first change has been confirmed by the server or B) 1000 ms have passed.

I’m basically doing the same thing. The client always waits for a response from the server (success or failure) or times out before sending a new message. So there’s always at most one open request at a time.

My implementation also has only a single open request at a time, but when the send request finishes, you still have to take care not to immediately start another one (when you still have pending changes).

Yes, I always make sure to call receive on the collab module before “releasing the lock”.

I haven’t checked the demo collab code in a while and I’m using sockets in my implementation so the following points might not apply, but these are additional edge cases that I’m handling on the client:

  • After confirming steps (regardless of whether the steps originated on the current client or someone else), make sure to send new locally pending steps if there are any. Otherwise it is possible for the last few steps to not get synced in case the user stopped typing while new steps were being received/transmitted (and no one else is typing anymore).
  • If we get a “new version” message while there is an already open getSteps request, schedule another getSteps request for when the current request finishes. Otherwise it is possible that we do not sync the latest few steps from other clients (if no one is typing anymore).

We haven’t run into syncing issues for quite some time now, so I’m confident that it is fairly robust by now.