Skip to content

fix(rust_brain): preserve HLC on snapshot restore and gossip receive#34

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-b4db
Draft

fix(rust_brain): preserve HLC on snapshot restore and gossip receive#34
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-b4db

Conversation

@cursor

@cursor cursor Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

After v0.6.0 added HLC monotonic enforcement, restore_from_file() and gossip.receive() did not preserve or apply HLC timestamps from snapshots or peer events.

Concrete trigger: Snapshot a node with hlc=(5000, 10, "nodeA"), restore, then apply a causal successor write with hlc=(5000, 11, "nodeA"). Restore assigns a fresh wall-clock HLC, so the legitimate successor write raises TimestampRegression — silent data loss on disaster recovery and replication.

Gossip without HLC could also overwrite fresher local data.

Root cause

  • restore_from_file() rebuilt MemoryNode without the snapshot hlc field (default factory assigned a new HLC).
  • bulk_write() and gossip.receive() did not pass through HLC from incoming rows/events.

Fix

  • Add _parse_hlc() for snapshot/wire normalization (with legacy fallback from ts_ns).
  • Restore HLC on snapshot restore and call _hlc.update() per restored node.
  • Pass HLC through bulk_write and gossip.receive(); reject stale gossip updates and skip missing-HLC overwrites on existing keys.

Validation

  • Reproduced bug on main before fix.
  • Added regression tests: test_restore_preserves_hlc_for_replication, gossip HLC tests.
  • pytest tests/test_enterprise_backup.py::test_restore_preserves_hlc_for_replication tests/test_gossip.py tests/test_rust_brain.py tests/test_rust_brain_concurrency.py — 30 passed.
Open in Web View Automation 

After v0.6.0 added HLC monotonic enforcement, restore_from_file() and
gossip.receive() did not preserve or apply HLC timestamps. Snapshot restore
assigned fresh HLCs, causing legitimate causal successor writes to raise
TimestampRegression (silent data loss). Gossip without HLC could overwrite
fresher local data.

- Add _parse_hlc() for snapshot/wire normalization
- Restore HLC and update global clock on snapshot restore
- Pass HLC through bulk_write and gossip receive with stale rejection

Co-authored-by: Daniel <DJLougen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant