Skip to main content

How conflicts happen

Even with leases, version conflicts can occur:
  • A terminal sends ORDER_SNAPSHOT { baseVersion: 3 } but the hub already has version 4
  • A terminal reconnects after a network drop and sends a stale snapshot
  • Two terminals briefly hold overlapping leases during the disconnect grace period

Version tracking

Every order in the hub has an auto-incrementing version number:
When a terminal sends ORDER_SNAPSHOT { baseVersion }:
  1. Hub compares baseVersion against the stored version
  2. If baseVersion >= storedVersion: accept, increment version, broadcast
  3. If baseVersion < storedVersion: reject, send CONFLICT { hubVersion, hubSnapshot }

Hub-side conflict detection

In nu_pos_hub/src/handlers/orderHandler.ts:
The hub always has the authoritative version. Terminals must resolve conflicts before retrying.

Frontend reconciliation

When the terminal receives a CONFLICT message, reconcile() in nu_pos_react/src/realtime/sync/reconcile.ts decides what to do.

Strategies

Decision flow

Merge logic

When a merge is possible (terminal is exactly 1 version behind with local-only line additions):
1

Build remote set

Build a set of remote line IDs
2

Find local-only lines

Find local lines whose IDs are not in the remote set (these are new additions)
3

Concatenate

remote.lines + localOnlyLines
4

Recalculate totals

remote.totals + sum(localOnlyLines)
This handles the common case of two terminals adding items to the same order concurrently.

Example

UI integration

When a conflict occurs, the SyncUIProvider shows a ConflictDialog:
  • “Load Latest” — Calls reconcile() with accept_remote, replaces local order state
  • “Keep Mine” — User decides to discard the remote and try to re-send (rare)
The dialog shows the order reference, hub version number, and number of lines in the hub version.

Conflict prevention

The best conflict resolution is prevention. The system minimizes conflicts through:
  1. Leases — Only the lease holder can submit snapshots
  2. Heartbeats — Keep leases alive during active editing
  3. Optimistic versioning — Send baseVersion with every snapshot so the hub can detect staleness
  4. Instant broadcast — Other terminals see changes in real-time, reducing the window for stale edits