Skip to content

refactor(query): add QueryDatastoreReader to act as an implementation shim for datastores#2956

Merged
barakmich merged 4 commits intomainfrom
barakmich/querydatastore
Mar 11, 2026
Merged

refactor(query): add QueryDatastoreReader to act as an implementation shim for datastores#2956
barakmich merged 4 commits intomainfrom
barakmich/querydatastore

Conversation

@barakmich
Copy link
Contributor

@barakmich barakmich commented Mar 5, 2026

Description

Currently, there are very few calls in pkg/query direct to the datastore interface. We'd like to keep this interface minimal, in an effort to start to clean up datastores over time as we continue with query planner.

This has the added benefit of being a way to inject various testing scenarios directly with the query planner tests and benchmarks; for example, adding a slight delay on any call to simulate a network latency.

@barakmich barakmich requested a review from a team as a code owner March 5, 2026 23:25
@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 5, 2026
@codecov
Copy link

codecov bot commented Mar 6, 2026

Codecov Report

❌ Patch coverage is 56.75676% with 144 lines in your changes missing coverage. Please review.
✅ Project coverage is 74.85%. Comparing base (70f05dd) to head (a5fa991).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/query/datastore.go 54.08% 61 Missing and 1 partial ⚠️
pkg/query/reader.go 68.67% 35 Missing and 12 partials ⚠️
pkg/query/reader_timing.go 0.00% 33 Missing ⚠️
internal/services/v1/permissions_queryplan.go 0.00% 1 Missing ⚠️
pkg/query/context.go 66.67% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2956      +/-   ##
==========================================
+ Coverage   74.84%   74.85%   +0.01%     
==========================================
  Files         496      498       +2     
  Lines       60695    60746      +51     
==========================================
+ Hits        45423    45466      +43     
- Misses      12118    12120       +2     
- Partials     3154     3160       +6     

☔ 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.

@barakmich barakmich force-pushed the barakmich/querydatastore branch 3 times, most recently from 9cf3d40 to d45a485 Compare March 6, 2026 17:52
Copy link
Contributor

@miparnisari miparnisari left a comment

Choose a reason for hiding this comment

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

could you edit the description of this PR to explain the motivation behind this change? you prefixed it with feat but this strikes me as a refactor.

resourceIDs[i] = res.ObjectID
}

// All resources in a DatastoreIterator share the same type.
Copy link
Contributor

@miparnisari miparnisari Mar 6, 2026

Choose a reason for hiding this comment

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

is DatastoreIterator the only expected caller of this method?
more generally, maybe rephrase this to write an expectation of all callers: "it is assumed that callers of this method pass in resources that share a type". i'm also thinking that we could be defensive on this and reuse the for loop above to validate this assumption, which won't cost any extra cpu cycles

    resourceIDs := make([]string, len(resources))
	resourceType := resources[0].ObjectType
	for i, res := range resources {
		resourceIDs[i] = res.ObjectID
		if res.ObjectType != resourceType {
			return nil, fmt.Errorf("expected resource type %q but got %q", resourceType, res.ObjectType)
		}
	}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, this is worth a signature change. Fixed.

wildcardSubject := ObjectAndRelation{
ObjectType: subject.ObjectType,
ObjectID: WildcardObjectID,
Relation: subject.Relation,
Copy link
Contributor

@miparnisari miparnisari Mar 6, 2026

Choose a reason for hiding this comment

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

wouldn't it it be a bug if subject.Relation != ""?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added invariants

Copy link
Contributor

@miparnisari miparnisari Mar 6, 2026

Choose a reason for hiding this comment

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

for a follow up PR, can you please add more unit tests to this file? in https://app.codecov.io/gh/authzed/spicedb/blob/main/pkg%2Fquery%2Fdatastore.go i see that there are large blocks of code not covered by anything

miparnisari
miparnisari previously approved these changes Mar 6, 2026
Copy link
Contributor

@miparnisari miparnisari left a comment

Choose a reason for hiding this comment

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

overall LGTM, just some questions and one suggested follow-up

tstirrat15
tstirrat15 previously approved these changes Mar 9, 2026
Copy link
Contributor

@tstirrat15 tstirrat15 left a comment

Choose a reason for hiding this comment

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

See comment, otherwise LGTM

// LookupCaveatDefinition individually for each name.
type caveatDefinitionLookupAdapter struct{ r QueryDatastoreReader }

func (a caveatDefinitionLookupAdapter) LookupCaveatDefinitionsByNames(
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the idea with this shim that we'd eventually have a bulk method that isn't making individual requests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or uses the underlying cache, but yes, that's an eventual benefit.

@barakmich barakmich changed the title feat(query): add QueryDatastoreReader to act as an implementation shim for datastores refactor(query): add QueryDatastoreReader to act as an implementation shim for datastores Mar 11, 2026
@barakmich barakmich dismissed stale reviews from tstirrat15 and miparnisari via c43c621 March 11, 2026 21:52
@barakmich barakmich force-pushed the barakmich/querydatastore branch 2 times, most recently from c43c621 to 0aa62e6 Compare March 11, 2026 21:53
@barakmich barakmich force-pushed the barakmich/querydatastore branch from 0aa62e6 to a5fa991 Compare March 11, 2026 23:09
@barakmich barakmich enabled auto-merge (squash) March 11, 2026 23:21
@barakmich barakmich merged commit 9d4d4b7 into main Mar 11, 2026
42 of 44 checks passed
@barakmich barakmich deleted the barakmich/querydatastore branch March 11, 2026 23:22
@github-actions github-actions bot locked and limited conversation to collaborators Mar 11, 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) Skip-Changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants