Context
Currently all WebSocket events flow through the same path with identical handling. Sim separates two distinct channels with different reliability and performance characteristics:
- Structural channel (pessimistic) — node create/delete, edge create/delete. Persist first, then broadcast.
- Value channel (optimistic) — text edits, subblock updates. Broadcast immediately, persist with server-side coalescing/debounce.
Position updates (node move/drag) are a special case: broadcast immediately for smooth collaborative dragging, persist on drag-end.
What to build
Backend: Two processing paths
- Structural handler: Validates → persists to DB → broadcasts to peers → sends ack to sender
- Value handler: Validates → broadcasts to peers → coalesces writes → persists in batch (25ms window)
- Position handler: Broadcasts immediately → persists on
node_drag_end
Frontend: Channel-aware send
- Tag outbound events with their channel type, or route by event type
- Structural ops wait for ack before marking complete in operation queue
- Value ops are optimistic (no ack wait)
Server-side coalescing
- For value updates targeting the same field within a coalescing window (~25ms), only persist the final value
- Reduces DB writes from hundreds to dozens for a typical typing session
Current code references
services/collab/src/main/java/com/leetdoodle/collab/handler/CanvasWebSocketHandler.java — handleCanvasEvent() treats all events identically
frontend/src/shared/events.ts — event type definitions (no channel distinction today)
Acceptance criteria
Context
Currently all WebSocket events flow through the same path with identical handling. Sim separates two distinct channels with different reliability and performance characteristics:
Position updates (node move/drag) are a special case: broadcast immediately for smooth collaborative dragging, persist on drag-end.
What to build
Backend: Two processing paths
node_drag_endFrontend: Channel-aware send
Server-side coalescing
Current code references
services/collab/src/main/java/com/leetdoodle/collab/handler/CanvasWebSocketHandler.java—handleCanvasEvent()treats all events identicallyfrontend/src/shared/events.ts— event type definitions (no channel distinction today)Acceptance criteria