Skip to content

Storage operation correctness#1964

Closed
cursor[bot] wants to merge 1 commit intofeat/sim-node-storage-infrafrom
cursor/storage-operation-correctness-3369
Closed

Storage operation correctness#1964
cursor[bot] wants to merge 1 commit intofeat/sim-node-storage-infrafrom
cursor/storage-operation-correctness-3369

Conversation

@cursor
Copy link
Contributor

@cursor cursor bot commented Feb 12, 2026

Node Simulation: Fix hierarchical insertion cycle and buffered write metrics

Description

This PR addresses two issues in the node simulation:

  1. Hierarchical Insertion Cycle (c401c861-d6fc-4d22-9da8-75c1e1d19b96): Previously, insert_entity_hierarchical could create a self-referencing cycle if an entity's storage_id was identical to an intermediate node ID (e.g., EntityId::from_u64(0) with depth >= 1), leading to infinite recursion. The fix prevents an intermediate node from being created if its ID matches the entity's storage_id, thus avoiding the entity becoming its own parent.
  2. Missing Buffered Write Metrics (3526d11-bec2-4273-8e13-f892ab6652c0): The SyncComplete handler failed to record self.metrics.work.record_write() for storage operations replayed from the buffer, causing an undercount of actual storage writes. The fix adds the record_write() call for each replayed buffered operation, ensuring consistent metric tracking.

Test plan

The changes are within the crates/node/tests/sync_sim module.

  • For the metrics fix, existing simulation tests that involve SyncComplete events and buffered operations should now correctly reflect the work.writes count.
  • For the hierarchical insertion fix, the change prevents a specific edge case that could lead to infinite recursion. While current test generators avoid this, a dedicated test case for EntityId::from_u64(0) with depth >= 1 could be added to explicitly verify this fix. The current simulation tests are expected to pass without issues.

Documentation update

No public or internal documentation updates are required as these changes are confined to test utilities.


…d writes

- Fix hierarchical insertion creating self-referencing cycles when entity
  key bytes after position depth are all zeros. Now skips intermediate nodes
  that would equal the entity's storage_id.

- Fix replayed buffered writes in SyncComplete handler not being recorded
  in work metrics. Now calls record_write() for each replayed operation,
  consistent with the GossipDelta handler.
@cursor
Copy link
Contributor Author

cursor bot commented Feb 12, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@github-actions
Copy link

Your PR title does not adhere to the Conventional Commits convention:

<type>(<scope>): <subject>

Common errors to avoid:

  1. The title must be in lower case.
  2. Allowed type values are: build, ci, docs, feat, fix, perf, refactor, test.

Copy link

@meroreviewer meroreviewer bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Code Reviewer

Reviewed by 3 agents | Quality score: 100% | Review time: 196.3s

🟡 1 warnings, 💡 1 suggestions. See inline comments.


🤖 Generated by AI Code Reviewer | Review ID: review-f4946ce9

let mut intermediate_key = [0u8; 32];
intermediate_key[..d].copy_from_slice(&key[..d]);

let intermediate_id = Id::new(intermediate_key);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Edge case fix lacks dedicated test coverage

The PR description acknowledges that 'a dedicated test case for EntityId::from_u64(0) with depth >= 1 could be added' but doesn't include one; this self-referencing cycle fix is a critical correctness guard that should have explicit test coverage.

Suggested fix:

Add a unit test that explicitly creates an entity with EntityId::from_u64(0) at depth >= 1 and verifies no cycle is created and the hierarchy is valid.

let mut intermediate_key = [0u8; 32];
intermediate_key[..d].copy_from_slice(&key[..d]);

let intermediate_id = Id::new(intermediate_key);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Comment could clarify resulting hierarchy behavior

The comment explains that it prevents self-referencing cycles but doesn't mention that skipping these intermediate nodes results in a shallower hierarchy than the requested depth.

Suggested fix:

Expand comment to: '// Skip if this intermediate ID equals the entity's storage ID. This prevents self-referencing cycles when key[depth..] are all zeros, resulting in a shallower hierarchy at the matching entity's storage_id level.'

@xilosada
Copy link
Member

Fix incorporated into #1968 (commit 97b514e). Thank you!

@xilosada xilosada closed this Feb 12, 2026
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.

2 participants