Skip to content

feat(query): route carrier sum and count+sum reads through run_path_query - #805

Merged
QuantumExplorer merged 1 commit into
developfrom
claude/run-path-query-aggregate-per-key
Aug 14, 2026
Merged

feat(query): route carrier sum and count+sum reads through run_path_query#805
QuantumExplorer merged 1 commit into
developfrom
claude/run-path-query-aggregate-per-key

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

Follow-up to #803 (merged) and #798 (merged) — the dispatch wiring both PRs left open.

What this closes

run_path_query's AggregateCarrier arm served only the count axis and refused the other two by name:

AggregateKind::Sum | AggregateKind::CountAndSum => Err(Error::NotSupported(
    "carrier aggregate-sum reads have no trusted per-key read primitive; use \
     prove_query with verify_aggregate_sum_query_per_key / ..."
))

That was accurate when #798 landed — the readers didn't exist. #803 added them, so the arm now routes all three axes:

AggregateKind reader
Count query_aggregate_count_per_key
Sum query_aggregate_sum_per_key (newly reachable)
CountAndSum query_aggregate_count_and_sum_per_key (newly reachable)

Every shape classify() can produce now has a reader behind it. The only NotSupported the dispatch still raises is the read-mode version gate, which is intentional and unrelated. Module doc updated to say so.

The result-type decision

PathQueryRun gains two variants rather than collapsing the carrier family:

AggregateCountPerKey(Vec<(Vec<u8>, u64)>),             // existed
AggregateSumPerKey(Vec<(Vec<u8>, i64)>),               // new
AggregateCountAndSumPerKey(Vec<(Vec<u8>, u64, i64)>),  // new

The plan for this follow-up was to mirror a VerifiedPathQuery::AggregatePerKey { per_key: Vec<(Vec<u8>, Option<u64>, Option<i64>)> }. That type does not exist anywhere in the repo#798 shipped the read dispatch only, and its own module doc notes that "the unified proof dispatch arrives separately." With no mirror target, three typed variants win on every axis I can find:

  • Consistent with this enum's own leaf family one screen above: AggregateCount(u64) / AggregateSum(i64) / AggregateCountAndSum { count, sum }. Collapsing only the carrier half would make the two halves disagree.
  • Honest types. A sum carrier can never produce a count, so Option<u64> would be statically always-None on that axis — the collapsed shape encodes a value that can't occur.
  • Additive. AggregateCountPerKey is already public on develop; collapsing it is a breaking change to a just-shipped variant.
  • 1:1 with the readers, so the routing is a straight hand-off with no reshaping.

When the unified verify dispatch lands, it should mirror these three variants rather than the collapsed shape.

Tests

aggregate_carrier_count_matches_per_key_reader_and_others_are_refused existed to assert the refusal, so it is now aggregate_carrier_all_kinds_match_their_per_key_readers: a differential assertion per axis (unified answer == dedicated reader) over ProvableSumTree and PCPS carrier fixtures, plus a check of the values themselves so the test would catch both readers being wrong in the same way.

New: aggregate_carrier_per_key_dispatch_surfaces_reader_errors. Routing must not paper over a reader's rejection, so a non-tree outer match and a single-axis host under a combined carrier each have to fail through run_path_query with the same error text the dedicated reader produces.

Validation

  • cargo clippy --workspace --all-features -- -D warnings — clean (exit 0, zero diagnostics)
  • cargo test -p grovedb -p grovedb-query --all-features — 2633 + 255 pass, 0 fail
  • cargo build --no-default-features --features verify -p grovedb — clean
  • cargo fmt --check — clean

No version gating: purely additive routing over readers that are already gated on their own existing slots (query_aggregate_{sum,count_and_sum}_on_range), so no new slots and no V4 gate.

🤖 Generated with Claude Code

…uery

Closes the last `NotSupported` in the unified read dispatch. Before this,
`run_path_query`'s `AggregateCarrier` arm served only the count axis and
refused the sum and count+sum kinds by name, pointing callers at
prove_query + the per-key verifiers. #803 added the missing trusted
readers, so the arm can now route all three axes:

  AggregateKind::Count       -> query_aggregate_count_per_key
  AggregateKind::Sum         -> query_aggregate_sum_per_key          (new)
  AggregateKind::CountAndSum -> query_aggregate_count_and_sum_per_key (new)

Every shape `classify()` can produce now has a reader behind it; the only
`NotSupported` the dispatch still raises is the read-mode version gate.

`PathQueryRun` gains two variants — `AggregateSumPerKey(Vec<(Vec<u8>,
i64)>)` and `AggregateCountAndSumPerKey(Vec<(Vec<u8>, u64, i64)>)` —
rather than collapsing the carrier family into one `Option`-bearing
variant. Three reasons: it matches how the leaf family in the same enum is
already shaped (`AggregateCount` / `AggregateSum` /
`AggregateCountAndSum`); each axis maps 1:1 onto its reader's return type
with no `Option` that is statically always-None; and `AggregateCountPerKey`
is already public, so this stays additive.

The original plan for this follow-up was to mirror a
`VerifiedPathQuery::AggregatePerKey { per_key: Vec<(Vec<u8>, Option<u64>,
Option<i64>)> }`, but that type does not exist — #798 shipped the read
dispatch only, and its module doc notes the unified proof dispatch arrives
separately. With no mirror target, matching the enum's own existing
convention wins. When the unified verify dispatch does land it should
mirror these three variants rather than the collapsed shape.

Tests: `aggregate_carrier_count_matches_per_key_reader_and_others_are_refused`
asserted the refusal, so it becomes
`aggregate_carrier_all_kinds_match_their_per_key_readers` — a differential
assertion per axis (unified answer == dedicated reader) plus a check of the
values themselves, over ProvableSumTree and PCPS carrier fixtures. Adds
`aggregate_carrier_per_key_dispatch_surfaces_reader_errors`: a non-tree
outer match and a single-axis host under a combined carrier must fail
through the dispatch with the same error text the dedicated reader
produces, so routing can't paper over a reader's rejection.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.27%. Comparing base (44a6260) to head (dbe548d).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop     #805   +/-   ##
========================================
  Coverage    92.27%   92.27%           
========================================
  Files          265      265           
  Lines        79920    79922    +2     
========================================
+ Hits         73750    73752    +2     
  Misses        6170     6170           
Components Coverage Δ
grovedb-core 90.60% <100.00%> (+<0.01%) ⬆️
merk 93.13% <ø> (ø)
storage 87.00% <ø> (ø)
commitment-tree 96.05% <ø> (ø)
mmr 96.79% <ø> (ø)
bulk-append-tree 89.82% <ø> (ø)
element 97.92% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Reviewed

@QuantumExplorer
QuantumExplorer merged commit 1fd576c into develop Aug 14, 2026
10 of 11 checks passed
@QuantumExplorer
QuantumExplorer deleted the claude/run-path-query-aggregate-per-key branch August 14, 2026 10:32
@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d27904d-cf10-461b-ba29-75474ce4ff90

📥 Commits

Reviewing files that changed from the base of the PR and between 44a6260 and dbe548d.

📒 Files selected for processing (2)
  • grovedb/src/operations/get/run_path_query.rs
  • grovedb/src/tests/run_path_query_tests.rs

Comment @coderabbitai help to get the list of available commands.

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