Problem
history.list returns every version row a document has, with no page size (apps/hocuspocus.server/src/lib/history-stateless.ts:107). The query passes no take and no cursor. grep -c 'take' apps/hocuspocus.server/src/lib/history-stateless.ts returns 0.
The same reply also ships the newest full document snapshot (apps/hocuspocus.server/src/lib/history-stateless.ts:141).
That snapshot is base64-encoded from the whole document buffer (apps/hocuspocus.server/src/lib/history-stateless.ts:90). The encode is synchronous. It runs in the WebSocket server process, which also serves live sync for every other open document (apps/hocuspocus.server/src/hocuspocus.server.ts:312).
So both the reply size and the encode cost grow with the document, and neither has a bound.
What to do
Page the version list. Accept a page size and a cursor, and return one page.
Remove latestSnapshot from the list reply. A caller that needs document bytes can ask for them with history.watch, which returns a snapshot for one version.
Acceptance
Notes
No one has measured the delay this adds to live sync. The size and the missing bound are read from the code, not from a profile. A measurement on a large document would size the win before the work starts.
A per-connection cooldown of 250 ms already limits repeat history.list calls (apps/hocuspocus.server/src/hocuspocus.server.ts:113). It caps how often one client asks. It does not cap the cost of a single reply.
Problem
history.listreturns every version row a document has, with no page size (apps/hocuspocus.server/src/lib/history-stateless.ts:107). The query passes notakeand no cursor.grep -c 'take' apps/hocuspocus.server/src/lib/history-stateless.tsreturns0.The same reply also ships the newest full document snapshot (
apps/hocuspocus.server/src/lib/history-stateless.ts:141).That snapshot is base64-encoded from the whole document buffer (
apps/hocuspocus.server/src/lib/history-stateless.ts:90). The encode is synchronous. It runs in the WebSocket server process, which also serves live sync for every other open document (apps/hocuspocus.server/src/hocuspocus.server.ts:312).So both the reply size and the encode cost grow with the document, and neither has a bound.
What to do
Page the version list. Accept a page size and a cursor, and return one page.
Remove
latestSnapshotfrom the list reply. A caller that needs document bytes can ask for them withhistory.watch, which returns a snapshot for one version.Acceptance
history.liston a document with hundreds of versions returns one bounded page plus a cursor.history.listreply carries no base64 document data.Notes
No one has measured the delay this adds to live sync. The size and the missing bound are read from the code, not from a profile. A measurement on a large document would size the win before the work starts.
A per-connection cooldown of 250 ms already limits repeat
history.listcalls (apps/hocuspocus.server/src/hocuspocus.server.ts:113). It caps how often one client asks. It does not cap the cost of a single reply.