Skip to content

feat(qp): prune branches that cannot lead to the subject type of the …#2968

Merged
miparnisari merged 3 commits intomainfrom
qp-subject-type-shear
Mar 17, 2026
Merged

feat(qp): prune branches that cannot lead to the subject type of the …#2968
miparnisari merged 3 commits intomainfrom
qp-subject-type-shear

Conversation

@miparnisari
Copy link
Contributor

@miparnisari miparnisari commented Mar 11, 2026

…request

Description

This is an optimization for Check API when using the query planner. We prune branches of the tree that can never lead to the subject type in the request.

Testing

Unit tests

References

@github-actions github-actions bot added area/api v1 Affects the v1 API area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools) labels Mar 11, 2026
@codecov
Copy link

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 93.40659% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.84%. Comparing base (e49cc12) to head (17b9ff3).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
internal/services/v1/permissions_queryplan.go 0.00% 4 Missing ⚠️
pkg/query/queryopt/caveat_pushdown.go 75.00% 1 Missing ⚠️
pkg/query/queryopt/reachability_pruning.go 98.08% 1 Missing ⚠️

❌ Your project status has failed because the head coverage (74.84%) is below the target coverage (75.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2968      +/-   ##
==========================================
+ Coverage   74.82%   74.84%   +0.02%     
==========================================
  Files         497      498       +1     
  Lines       60656    60736      +80     
==========================================
+ Hits        45382    45451      +69     
- Misses      12115    12123       +8     
- Partials     3159     3162       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@miparnisari miparnisari marked this pull request as ready for review March 11, 2026 16:59
@miparnisari miparnisari requested a review from a team as a code owner March 11, 2026 16:59
@miparnisari miparnisari marked this pull request as draft March 12, 2026 00:42
@miparnisari miparnisari force-pushed the qp-subject-type-shear branch from 9779e99 to 16bdda5 Compare March 16, 2026 20:17
@miparnisari miparnisari marked this pull request as ready for review March 16, 2026 20:17
@miparnisari miparnisari force-pushed the qp-subject-type-shear branch from 16bdda5 to e733393 Compare March 16, 2026 20:18
@miparnisari miparnisari enabled auto-merge (squash) March 16, 2026 21:11
Copy link
Contributor

@barakmich barakmich left a comment

Choose a reason for hiding this comment

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

So I think this could be simplified, namely, creating a closure that understands the targetSubjectType, calls MutateOutline (which walks bottom up https://github.com/authzed/spicedb/blob/main/pkg/query/mutations.go#L9) -- though MutateOutline might need to become a little more aware of what happens if the function it's passed returns a null type -- and then simply return a null if it's a datastore iterator and the types don't match.

The tests however should totally still work 🙂

return nil, ps.rewriteError(ctx, err)
}

optimized = queryopt.ApplyReachabilityPruning(optimized, req.Subject.Object.ObjectType)
Copy link
Contributor

Choose a reason for hiding this comment

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

We should make this a little more generalized (ie, this is the first request-parameterized optimization!) but this is fine for now.

func ApplyReachabilityPruning(co query.CanonicalOutline, targetSubjectType string) query.CanonicalOutline {
pruned, _ := pruneOutline(co.Root, targetSubjectType)

// TODO do i need to call FillMissingIds?
Copy link
Contributor

Choose a reason for hiding this comment

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

Not if it's just pruning 🙂

@miparnisari miparnisari force-pushed the qp-subject-type-shear branch from ec093ce to 17b9ff3 Compare March 17, 2026 07:09
Copy link
Contributor

@barakmich barakmich left a comment

Choose a reason for hiding this comment

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

Approved, with two small changes

// their existing IDs. Newly synthesized nodes (ID==0) receive fresh IDs via
// query.FillMissingNodeIDs. The returned CanonicalOutline is ready to compile.
func ApplyOptimizations(co query.CanonicalOutline, names []string) (query.CanonicalOutline, error) {
func ApplyOptimizations(co query.CanonicalOutline, names []string, requestParams RequestParams) (query.CanonicalOutline, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I dig it 🙂

// NewTransform creates a whole-tree transformation for this optimizer,
// optionally using request-specific parameters. Each transform typically
// calls query.MutateOutline internally with its own mutations.
NewTransform func(RequestParams) OutlineTransform
Copy link
Contributor

Choose a reason for hiding this comment

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

I would do one little trick here, which is to name this signature (eg, RequestOutlineTransform, under the above) and have a simple identity helper that wraps it (turning the caveat pushdown into something like NewTransform: withoutRequestParams(caveatPushdown))

@miparnisari miparnisari merged commit 0298415 into main Mar 17, 2026
44 of 45 checks passed
@miparnisari miparnisari deleted the qp-subject-type-shear branch March 17, 2026 22:33
@github-actions github-actions bot locked and limited conversation to collaborators Mar 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area/api v1 Affects the v1 API area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants