← React / TypeScript

React / TypeScript · 18 / 18

Shared editing with WebSockets and PostgreSQL

Understand ordered operations, reconnection and a durable operation log’s role.

  • Large
  • Advanced
  • 120 min

Prerequisites: Persistent optimistic UI, replay and conflicts

A collaborative interface needs more than an open WebSocket. Clients must know which changes the server confirmed and which they missed during interruption. Realtime Collaboration Lab stores durable ordering in PostgreSQL. A WebSocket distributes messages. LISTEN/NOTIFY signals changes but does not persist them. We start with a small executable sequence check, then follow the same workflow through the complete project.

01Trace ordering locally

The learning client holds lastSequence and text state. An operation with an already known sequence is not applied twice. A gap produces an explicit error. The simulator opens no WebSocket connection. It isolates this one rule.

sequence.mjs · javascriptOpen file
class ClientState {
  sequence = 0;
  title = '';
  apply(operation) {
    if (operation.sequence <= this.sequence) return;
    if (operation.sequence !== this.sequence + 1) throw new Error('Sequence gap: request recovery');
    this.title = operation.title; this.sequence = operation.sequence;
  }
  snapshot(value) { this.sequence = value.sequence; this.title = value.title; }
}
const client = new ClientState();
client.apply({ sequence: 1, title: 'First' });
client.apply({ sequence: 1, title: 'First' });
try { client.apply({ sequence: 3, title: 'Third' }); }
catch (error) { console.log(error.message); }
client.snapshot({ sequence: 3, title: 'Third' });
client.apply({ sequence: 4, title: 'Fourth' });
console.log(client.sequence, client.title);

Run / check

node sequence.mjs

02Set up the complete application

Setup clones a pinned public source version into a new learning folder. Install its documented Node.js and pnpm versions. pnpm verify checks code and unit contracts. Then start PostgreSQL according to the linked gateway runbook using your own local DATABASE_URL.

setup.sh · bashOpen file
git clone https://github.com/wasiliy-strecker/realtime-collaboration-lab.git realtime-collaboration-lab-learning
cd realtime-collaboration-lab-learning
git checkout f42a832c68c2ee750b37c3b5de6e1fc0fddcc90c
corepack pnpm install --frozen-lockfile
corepack pnpm verify

03Trace an operation through the server

Read collaboration.ts and postgres/store.ts. The server checks the contract and performs the durable change in a transaction. Only after successful persistence may the operation be distributed as confirmed. Presence is transient and does not replace persisted domain information.

04Catch up after interruption

A client reports its confirmed state. The server supplies missing operations or a suitable snapshot. A single message does not establish a complete state. In the simulator, snapshot 3 replaces the missing sequence before sequence 4 is applied.

05Distinguish conflicts and duplicates

A repeated operation is not automatically a new user intent. Stable IDs help recognise the same intent. Contradictory changes still need domain decisions. A gap-free sequence defines ordering rather than a universal conflict solution.

06Test multiple clients and failures

Run pnpm dev:gateway and pnpm dev:web in separate terminals according to the README. Open two browser windows. Change a record, disconnect one client and reconnect it. The Playwright suite tests such scenarios using the real gateway and PostgreSQL. Compare both confirmed states at the end.

Expected result

The simulator detects the gap, accepts snapshot 3 and reaches sequence 4 exactly once. In the full project, clients recover missing confirmed operations.

Data flow
  1. React intent
  2. WebSocket contract
  3. PostgreSQL transaction
  4. Operation log / sequence
  5. Acknowledgement / recovery

Your exercise

In the simulator, add operation 2 after snapshot 3. What should happen? Also test a lost acknowledgement in the real multi-client workflow.

Show the solution and explanation

Operation 2 is already covered by the snapshot and is ignored. When an acknowledgement is lost, repeat the same domain operation ID. The server must not apply it as a new effect. A test checks both resulting state and confirmed sequence.

Project context and sources

The example is simplified for learning. The linked source version shows its use in the project and the checks applied there.