Two hard-coded limits introduced in 10.0.x make a local-first app lose data silently, and there is no way to configure them or to be notified.
1. HLC_MAX_FUTURE_OFFSET (5 min)
validateMergeable walks the whole MergeableContent / MergeableChanges tree and, if any stamp is more than 5 minutes ahead of the local clock, applyMergeableChanges and setMergeableContent return the store unchanged. No error is thrown and onIgnoredError is not called. Observed effects (10.0.1):
- A mixed diff (one cell from a device with a fast clock, others valid) is dropped entirely, valid cells included.
- Hydrating a persisted blob that contains 2 "future" cells out of ~1000 rows leaves 0 rows.
- A device whose own clock is 10 min behind loads 0 rows from content written by other devices in the last few minutes.
- With an IndexedDB-style persister that keeps an in-memory mirror and writes it back whole, the mirror hydrates empty and the next save overwrites the stored content.
2. MAX_WEBSOCKET_BUFFER_SIZE (16 MiB)
For an empty client, the first GetRowDiff response of a large table is sent as one message. With ~20 MB of content we measured a 15.7 MB message; slightly larger stores get a 1013 close and the client never syncs. The same constant also limits fragment reassembly and back-pressure, so fragmentSize does not raise the logical ceiling.
What we do today: a pnpm patch setting both constants to Infinity (restoring 8.x behaviour), plus our own server-side warning when an incoming stamp is ahead of the server clock.
Request
- Options to configure both limits (e.g. on
createMergeableStore and on createWsServer / createWsSynchronizer), including disabling them.
- When content or changes are rejected by validation, report it through
onIgnoredError (or a similar callback) instead of returning silently, so apps can alert instead of losing data.
Happy to provide a minimal reproduction if useful.
Two hard-coded limits introduced in 10.0.x make a local-first app lose data silently, and there is no way to configure them or to be notified.
1.
HLC_MAX_FUTURE_OFFSET(5 min)validateMergeablewalks the wholeMergeableContent/MergeableChangestree and, if any stamp is more than 5 minutes ahead of the local clock,applyMergeableChangesandsetMergeableContentreturn the store unchanged. No error is thrown andonIgnoredErroris not called. Observed effects (10.0.1):2.
MAX_WEBSOCKET_BUFFER_SIZE(16 MiB)For an empty client, the first
GetRowDiffresponse of a large table is sent as one message. With ~20 MB of content we measured a 15.7 MB message; slightly larger stores get a 1013 close and the client never syncs. The same constant also limits fragment reassembly and back-pressure, sofragmentSizedoes not raise the logical ceiling.What we do today: a pnpm patch setting both constants to
Infinity(restoring 8.x behaviour), plus our own server-side warning when an incoming stamp is ahead of the server clock.Request
createMergeableStoreand oncreateWsServer/createWsSynchronizer), including disabling them.onIgnoredError(or a similar callback) instead of returning silently, so apps can alert instead of losing data.Happy to provide a minimal reproduction if useful.