Skip to content

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

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

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

Conversation

@cursor

@cursor cursor Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Bug and impact

Critical data-loss bug in distributed memory paths.

restore_from_file() and gossip.receive() did not preserve or apply Hybrid Logical Clock (HLC) timestamps introduced in v0.6.0. After a snapshot restore:

  1. Restored nodes received fresh HLCs instead of their saved timestamps.
  2. The global _hlc was not advanced to match restored state.
  3. Post-crash gossip replays with pre-crash HLCs were rejected as stale → silent write loss.
  4. Gossip events without HLC could overwrite fresher data on existing keys.

Concrete trigger: Node crashes, restores from snapshot, peer gossips a causal update with the original HLC → TimestampRegression is raised and the update is dropped.

Root cause

v0.6.0 (07a1c75) switched monotonic enforcement from ts_ns to hlc, but restore_from_file() and gossip.receive() were never updated to read/apply hlc fields. Snapshots stored HLC in JSON via to_dict(), but restore ignored them.

Fix

  • Add _parse_hlc() for snapshot/wire normalisation with legacy ts_ns fallback.
  • restore_from_file: restore hlc per node and call _hlc.update() to advance the process clock.
  • bulk_write: pass through hlc from row payloads.
  • gossip.receive: apply hlc, update clock, reject stale overwrites, skip missing-HLC updates on existing keys.

Validation

  • New tests: test_restore_preserves_hlc_for_replication, gossip stale/new/missing-hlc cases.
  • Full suite: 192 passed, 8 skipped.
Open in Web View Automation 

restore_from_file dropped hlc fields added in v0.6.0, assigning fresh
timestamps on restore. Post-crash causal writes and gossip replays with
pre-crash HLC were rejected (silent data loss), while gossip events
without HLC could overwrite fresher data.

- Add _parse_hlc() for snapshot/wire normalisation with legacy fallback
- restore_from_file: restore hlc and advance global _hlc per node
- bulk_write: pass through hlc from row payloads
- gossip.receive: apply hlc, reject stale updates, skip missing-hlc
  overwrites on existing keys
- Tests: snapshot HLC round-trip, gossip stale/new/missing-hlc cases

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