Skip to content

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

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

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

Conversation

@cursor

@cursor cursor Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

restore_from_file() and gossip.receive() dropped Hybrid Logical Clock (HLC) timestamps introduced in v0.6.0. After disaster recovery from a snapshot, restored nodes received fresh (wall, 0, uuid) HLCs instead of their original causal timestamps. Any subsequent write or gossip replay using the pre-crash HLC was rejected with TimestampRegression, causing silent data loss on recovery and cross-node sync.

Concrete trigger: Node writes remember("k", "v1", hlc=(5000, 10, "nodeA")), snapshots, crashes, restores. A causal successor remember("k", "v2", hlc=(5000, 11, "nodeA")) raises TimestampRegression because restore assigned a newer wall-clock HLC.

Root cause

restore_from_file() constructed MemoryNode without passing hlc from the snapshot dict (defaulting to a fresh HLC). gossip.receive() similarly omitted hlc/ts_ns when calling remember(). The global _hlc was never advanced to the max restored timestamp.

Fix

  • Add _parse_hlc() helper with legacy ts_ns fallback for pre-v0.6.0 snapshots
  • restore_from_file: restore hlc, call _hlc.update() per node, hold lock during restore
  • bulk_write: pass through hlc from row payloads
  • gossip.receive: apply hlc, reject stale overwrites, skip missing-HLC updates on existing keys

Validation

  • New regression tests: test_restore_preserves_hlc_for_replication, gossip HLC ordering tests
  • Full suite: 192 passed, 8 skipped
Open in Web View Automation 

restore_from_file() dropped HLC timestamps from snapshots, assigning fresh
(wall, 0, uuid) values instead. After disaster recovery, any causal
successor write with the pre-crash HLC was rejected with TimestampRegression,
causing silent data loss on replay/gossip.

- Add _parse_hlc() for wire/snapshot normalisation with legacy fallback
- restore_from_file: restore hlc, update global _hlc, hold lock during restore
- bulk_write: pass through hlc from row payloads
- gossip.receive: apply hlc, reject stale overwrites, skip missing-hlc updates

Regression tests cover snapshot round-trip and gossip HLC ordering.

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