Skip to content

feat(storage): overlap grouped hash operations with IS/IX and leaf locks - #439

Merged
thweetkomputer merged 2 commits into
mainfrom
hash-intent-operations
Nov 6, 2026
Merged

thweetkomputer merged 2 commits into
mainfrom
hash-intent-operations

Conversation

@thweetkomputer

@thweetkomputer thweetkomputer commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Context

Based directly on main. Existing grouped Hash commands serialize the whole key across page IO.

Behavior before and after

Standalone HGET/HMGET/HEXISTS/HSTRLEN, HSCAN and HLEN use IS; HSET/HMSET/HSETNX/HDEL/HINCRBY/HINCRBYFLOAT use IX with ordered leaf holds. Disjoint leaves can proceed while a conflicting command waits. Compact, full-value, externally locked and structural operations retain whole-key arbitration.

Implementation

Share the Hash-like intent adapter, refresh protected leaves across unrelated root publications, and prepare bounded Hash append batches. Merge changed-leaf count deltas into the latest root after resource waits, then allocate revision and sequence and stage without yielding. Retain the latest predecessor decision for recovery. Before a speculative replicated write, preserve its original replication request; an IX-to-X fallback discards attempt-derived canonical commands, expiration effects and publication coordinates before retrying against current key state.

Design decisions and alternatives

Splits, demotion, final deletion and oversized batches release all groups and intent before one X retry; no lock upgrade or retry loop. The shared adapter is also usable by Set, but this PR only enables Hash. The retry snapshot adds an owned command copy only for replicated intent writers; compact and unreplicated fast paths do not take this copy.

Documentation and comments

Updated transaction/grouped architecture and API/invariant comments. Durable formats are unchanged.

Test plan

The complete Hash/Set/sampling stack, rebased onto main including #445, passes the Debug build and 15 focused regressions covering intent concurrency, native-replica TTL fallback, sampling and latency diagnostics.

  • cmake --build build_debug --target lavik lavik_grouped_hash_write_e2e_test --parallel 6 — passed (Debug, ARM64).
  • build_debug/lavik_unit_tests --gtest_filter='GroupedHashTest.*:HashGroup*' — 52 passed.
  • build_debug/lavik_grouped_hash_write_e2e_test "$PWD/build_debug/lavik" --gtest_filter='GroupedHashWriteE2e.IntentRetryDiscardsPreviousIncarnationReplicationTTL:GroupedHashWriteE2e.StructuralRetryReleasesGroupsBeforeTakingKeyX' — 2 passed. The native-replica TTL case reproduced the missing-key divergence before the fix and passes after it; it also verifies TTL preservation on a successful IX attempt.
  • ctest --test-dir build_debug --output-on-failure -R '^lavik_grouped_hash_write_e2e\.(GroupedHashSetSamplingE2e\.|GroupedSetIntentE2e\.|GroupedHashWriteE2e\.(Intent|ConcurrentFinalDeletion|StructuralRetry))' — 13 passed on the combined Hash/Set/sampling stack, including both real primary/replica TTL regressions, in 83.88 seconds.

The complete reordered stack has the same Git tree as the previously built version. Its existing binary passed all 13 Hash/Set concurrency, sampling and native-replica TTL regressions again in 79.04 seconds:

build_debug/lavik_grouped_hash_write_e2e_test /tmp/lavik-stack-reorder-20261106/lavik-combined-before-reorder \
  --gtest_filter='GroupedHashSetSamplingE2e.*:GroupedSetIntentE2e.*:GroupedHashWriteE2e.Intent*:GroupedHashWriteE2e.ConcurrentFinalDeletion*:GroupedHashWriteE2e.StructuralRetry*'

The group-lock handoff fixture chooses a leaf with insertion capacity under its persisted seed, so it exercises lock handoff without an unrelated structural X-lock retry.

Risk assessment

Publication merging and structural fallback are the main risks. Tests cover disjoint count updates, conflicting wait/wake, structural fallback with a queued IX holder, and concurrent final deletion followed by cold recovery.

Rollback plan

Revert this change after reverting dependent Set/sampling changes; there is no disk-format migration.

Reviewer guide

Start with hash_api.cpp and MergeHashPublication, then review the late prepared-batch callback in grouped/mutation.cpp and the concurrency E2E tests.

Follow-up work

Enable the shared adapter for Set and separately add selected-leaf random operations.

Summary by CodeRabbit

  • New Features
    • Hash reads and writes can proceed concurrently on separate groups of a large collection, with whole-key locking retained for operations that require structural changes.
    • Sorted Set pop and range-removal operations protect their selected results while allowing some unrelated member operations to proceed.
    • Eligible grouped updates can merge disjoint changes into the latest collection state.
  • Documentation
    • Updated architecture guidance on grouped collection locking, retries, and publication behavior.
  • Tests
    • Added coverage for concurrent Hash and Sorted Set operations, retries, recovery, and replication.

@coderabbitai

coderabbitai Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Explain Change →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 45 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 6d3129d2-e3a8-4474-a6a8-9f0a579fcd0c
Commits

Reviewing files that changed from the base of the PR and between f294887 and bd2f382.

Files selected for processing: 14

  • docs/architecture/03-transaction-coordination.md
  • docs/architecture/09-grouped-collections.md
  • include/lavik/storage/detail/grouped/hash.h
  • include/lavik/storage/engine.h
  • src/storage/engine/grouped/hash.cpp
  • src/storage/engine/grouped/hash_random.cpp
  • src/storage/engine/grouped/mutation.cpp
  • src/storage/engine/grouped/read.cpp
  • src/storage/engine/hash_api.cpp
  • src/storage/engine/hash_tree.cpp
  • src/storage/engine/impl.h
  • src/storage/engine/write.cpp
  • tests/grouped/hash_test.cpp
  • tests/grouped/hash_write_e2e_test.cpp
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from 1edbdc6 to 786d2ad Compare November 6, 2026 05:07
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from 786d2ad to d6dd9d7 Compare November 6, 2026 06:13
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from d6dd9d7 to cff8721 Compare November 6, 2026 06:49
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from cff8721 to 7becdf9 Compare November 6, 2026 07:38
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from 7becdf9 to 213f827 Compare November 6, 2026 07:53
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from 213f827 to 3779d6d Compare November 6, 2026 08:18
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch 2 times, most recently from 6c74792 to bed42b6 Compare November 6, 2026 09:00
@thweetkomputer
thweetkomputer force-pushed the hash-intent-operations branch 2 times, most recently from b1445f8 to 3ddd040 Compare November 6, 2026 09:08
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from bed42b6 to 78124f2 Compare November 6, 2026 09:08
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from 78124f2 to a633b2a Compare November 6, 2026 09:18
@thweetkomputer
thweetkomputer force-pushed the zset-selection-intent-writes branch from a633b2a to 52be961 Compare November 6, 2026 09:26
Base automatically changed from zset-selection-intent-writes to main November 6, 2026 09:49
@thweetkomputer
thweetkomputer merged commit 8bf2b02 into main Nov 6, 2026
1 check passed
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