Skip to content

Real-time Sync with CRDT + WebSocket #284

@ElioNeto

Description

@ElioNeto

Real-time Sync with CRDT + WebSocket

Enable real-time, multi-device synchronization for notes using the existing CRDT engine and a WebSocket-based transport layer.

Existing Infrastructure

  • CrdtEngine in src/infra/crdt.rs — Last-Writer-Wins CRDT with timestamps
  • DataSync in src/infra/data_sync.rs — Diff computation and bidirectional sync
  • PubSub in src/infra/pubsub.rs — Topic-based pub/sub messaging
  • Replication in src/infra/replication.rs — WAL-based replication

Implementation

1. CRDT-based Note Storage

Wrap note writes with CRDT entries:

// On note write:
let crdt_entry = CrdtEntry {
    key: format!("note:{}", path).into_bytes(),
    value: content.as_bytes().to_vec(),
    timestamp: get_lamport_timestamp(device_id),
};
crdt_engine.merge(crdt_entry.key, crdt_entry.value, crdt_entry.timestamp);

2. WebSocket Transport

WS /ws/sync?device_id=device123
  • Server pushes changes as they happen (via PubSub)
  • Client sends local changes
  • Bidirectional conflict resolution via LWW

3. Sync Protocol

// Client -> Server: Push local changes
{
  "type": "sync_push",
  "changes": [
    { "key": "note:path", "value": "content", "timestamp": 123456, "device_id": "dev1" }
  ],
  "last_ack": 123450
}

// Server -> Client: Ack and push remote changes
{
  "type": "sync_ack",
  "ack_timestamp": 123456,
  "changes": [
    { "key": "note:path2", "value": "content2", "timestamp": 123457, "device_id": "dev2" }
  ]
}

4. Conflict Resolution

  • LWW (Last Writer Wins) by default
  • For concurrent edits, merge CRDT entries
  • Show conflict UI when timestamps are equal (same logical clock value)

Configuration

pub struct SyncConfig {
    pub device_id: String,
    pub sync_endpoint: Option<String>,
    pub sync_interval_ms: u64,  // fallback polling interval
    pub enable_websocket: bool,
}

Acceptance Criteria

  • CRDT entries maintain LWW semantics
  • WebSocket connection established and reconnected on failure
  • Changes propagate from device A to device B within 2s
  • Concurrent edits converge to the same state
  • Offline changes sync when reconnected
  • Conflict resolution works correctly
  • Unit tests for CRDT merge scenarios
  • Integration test with two simulated devices

Parent Epic

#275

Metadata

Metadata

Assignees

No one assigned

    Labels

    featnotesNote storage and indexingobsidianObsidian-like note-taking features

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions