Skip to content

Switch whiteboard collab to Excalidraw-style incremental scene sync (stop full-scene spam) #818

@hweihwang

Description

@hweihwang
  • Current state (ours):
    • Send: src/hooks/useSync.ts:186-211, 320-344 emits full SCENE_INIT every 500 ms from every
      client on any onChange (leading+trailing throttle), no diffing, no isDedicatedSyncer gate.
    • Receive: src/hooks/useCollaboration.ts:567-589 applies full element arrays; dedup is a JSON
      string compare scoped to the render, no versioning.
    • Echo: remote updateScene triggers onChange and re-sends the same scene.
    • Server: websocket_server/SocketManager.js:334 rebroadcasts blindly.
  • Problem: High baseline traffic and CPU just by being in a room; identical scenes bounce;
    SCENE_INIT is misused for ongoing updates; no message version/id; elements always sent, only
    files are hashed.
  • Main solution (follow Excalidraw collab pattern):
    • Upstream reference:
    • Adopt that model:
      1. Track scene version (or reuse computeElementVersionHash) and broadcast only when it
        increases; add a throttled full-scene fallback.
      2. Split message types: keep SCENE_INIT for first sync, add SCENE_UPDATE for incremental;
        include message version/id so receivers drop stale or duplicate updates.
      3. Gate scene broadcasts to isDedicatedSyncer; others send cursors/viewport only.
      4. Add a receive-side last-version ref to skip reapply without stringifying payloads.
      5. Prevent echo: mark remote-applied scenes so onChange does not rebroadcast them.
      6. Files/images: add a lightweight dataURL hash map to skip unchanged file sends; keep on
        reliable channel.
  • Impact: Much lower bandwidth and CPU per participant, fewer focus/interaction glitches for embeddables, clearer message semantics for future work.

Metadata

Metadata

Assignees

Type

No type

Projects

Status

🏗️ In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions