fix(hub-client): add onKeyDown guard for async Automerge change events#103
fix(hub-client): add onKeyDown guard for async Automerge change events#103shikokuchuo wants to merge 1 commit intomainfrom
Conversation
Automerge-repo's message pipeline has await boundaries between the WebSocket message and the DocHandle change event. This means the immediateFileChangeCallback can fire in a later microtask, leaving a window where a keystroke macrotask uses stale Monaco positions. Add a pre-input guard via editor.onKeyDown that syncs Monaco with Automerge before the keystroke is processed. A dirty flag (pendingRemoteSync) ensures the expensive getValue()+diff is only done when a remote change is actually pending — solo typing costs one boolean check per keystroke.
|
Thanks! I'll reiterate what I said at Asilomar, which is that we have plenty of time to redesign the monaco editor component. It might be a good idea to do so now that we have a better handle of the properties we need the system to hold. |
|
What seemed like an easy fix (originally in #100) appears to be really hard to pin down. The changes here are not sufficient. We probably should be looking more holistically at the integration. |
|
Following up a bit more. Have you investigated the automerge history to see if, like our high latency problems, there's a permanent record of the bug on the document? If that's the case, then we might be able to combine this with additional logging to get at a root cause. |
|
It's the Monaco side - the keystroke is getting lost without ever hitting the Automerge document. I need to look at greater depth into Monaco. |
Fixes #35. Follow-up to #100.
Bug
Automerge-repo's message pipeline has
awaitboundaries between the WebSocket message and the DocHandlechangeevent. The immediate callback from #102 fires in a later microtask, which usually drains before the next keystroke — but not always. In the rare case where a keystroke macrotask fires first, Monaco is still stale and characters land at wrong positions.Fix
Add an
editor.onKeyDownguard that syncs Monaco with Automerge before the keystroke is processed. ApendingRemoteSyncdirty flag (set only for remote changes via anisApplyingLocalguard) ensures the expensivegetValue()+ diff only runs when a remote change is actually pending. Solo typing costs one boolean check per keystroke.