Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend support for relationship filtering and add relationship filtering to other APIs #1739

Merged
merged 5 commits into from
Mar 13, 2024

Conversation

josephschorr
Copy link
Member

@josephschorr josephschorr commented Feb 7, 2024

Important

If a relationships filter is used without a resource type, there can be a performance impact due to the existing indexes all starting with the resource type. We may examine adding additional indexes in the future, but for now, the performance impact should be noted

  • Extends the relationship filter to allow for an optional resource_type, and a prefix for object IDs
  • Adds support for the relationship filter on BulkExport and Watch APIs

With this change, all objects can now be removed from the datastore with two calls (once with the object ID as the resource ID and once with it as the subject ID).

Fixes #315 (more or less; its two calls instead of one)

@josephschorr josephschorr requested review from vroldanbet and a team as code owners February 7, 2024 00:51
@github-actions github-actions bot added area/api v1 Affects the v1 API area/datastore Affects the storage system area/dependencies Affects dependencies area/tooling Affects the dev or user toolchain (e.g. tests, ci, build tools) labels Feb 7, 2024
pkg/datastore/datastore.go Show resolved Hide resolved
pkg/datastore/datastore.go Show resolved Hide resolved
pkg/datastore/datastore.go Show resolved Hide resolved
internal/services/v1/watch.go Show resolved Hide resolved
// If there are filters, we need to check if the update matches any of them.
matched := false
for _, filter := range filters {
// TODO(jschorr): Maybe we should add TestRelationship to avoid the conversion?
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a good compromise to avoid unnecessary allocations 🙏🏻

internal/services/v1/watch_test.go Show resolved Hide resolved
internal/services/v1/watch.go Show resolved Hide resolved
pkg/datastore/datastore.go Show resolved Hide resolved
pkg/datastore/datastore.go Show resolved Hide resolved
pkg/datastore/datastore.go Show resolved Hide resolved
@josephschorr josephschorr force-pushed the new-rel-filtering branch 3 times, most recently from 4b1ff59 to cfa8e45 Compare March 11, 2024 20:33
func (sqf SchemaQueryFilterer) MustFilterWithResourceIDPrefix(prefix string) SchemaQueryFilterer {
updated, err := sqf.FilterWithResourceIDPrefix(prefix)
if err != nil {
panic(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

I see that the other filters use this pattern as well, but I thought we had decided to avoid panics outside of tests?

Copy link
Member Author

Choose a reason for hiding this comment

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

This function is only called from tests

err,
codes.InvalidArgument,
spiceerrors.ForReason(
v1.ErrorReason_ERROR_REASON_UNSPECIFIED,
Copy link
Contributor

Choose a reason for hiding this comment

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

any reason to wait on defining a real reason here?

Copy link
Member Author

Choose a reason for hiding this comment

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

It requires an API repo change and I didn't want to block this change, so I left it as a TODO

}

return atRevision, cur, nil
return atRevision, decoded.GetV1().GetSections()[0], cur, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe a note about what this new return value is?

internal/datastore/common/sql.go Outdated Show resolved Hide resolved
internal/datastore/common/sql.go Show resolved Hide resolved
internal/datastore/common/sql.go Show resolved Hide resolved
internal/datastore/memdb/readonly.go Outdated Show resolved Hide resolved
index := indexNamespace
args := []any{filter.ResourceType}
if filter.OptionalResourceRelation != "" {
index := indexNamespace + "_prefix"
Copy link
Contributor

Choose a reason for hiding this comment

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

can you explain why _prefix was added to the default index? No index like that can be found in spicedb/internal/datastore/memdb/schema.go

Copy link
Member Author

Choose a reason for hiding this comment

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

Its a built-in to the backing memdb for prefix filtering; I'll add a note

internal/datastore/memdb/readwrite.go Show resolved Hide resolved
internal/datastore/memdb/readwrite.go Show resolved Hide resolved
internal/datastore/memdb/readwrite.go Show resolved Hide resolved
case err == nil:
break
nsClauses = append(nsClauses, sq.Eq{colNamespace: nsName})
Copy link
Contributor

Choose a reason for hiding this comment

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

a bit weird to see this here but seems correct

Copy link
Member Author

Choose a reason for hiding this comment

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

Has this changed appreciably?

Copy link
Contributor

Choose a reason for hiding this comment

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

it hasn't, just surprised me to see logic next to error handling

@@ -647,29 +669,30 @@ func queryForEach(
return cur, nil
}

func decodeCursor(ds datastore.Datastore, encoded *v1.Cursor) (datastore.Revision, *core.RelationTuple, error) {
func decodeCursor(ds datastore.Datastore, encoded *v1.Cursor) (datastore.Revision, string, *core.RelationTuple, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure to understand if the format of the cursor has changed, and if this is a breaking change.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, it has: we now have a namespace contained in it

Copy link
Contributor

Choose a reason for hiding this comment

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

in that case, don't we have a mechanism to version cursors already in place, and that we should be using it?

e.g. a cursor V1 is not compatible with cursor V2 or viceversa


// Datastore namespace order might not be exactly the same as go namespace order
// so we shouldn't assume cursors are valid across namespaces
cur = nil
Copy link
Contributor

Choose a reason for hiding this comment

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

can you clarify what happened here? I see a similar change was introduced earlier in the loop to make sure the cursor is reset for each iteration as the namespace changes

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure I follow

internal/services/v1/relationships.go Outdated Show resolved Hide resolved
internal/services/v1/relationships.go Outdated Show resolved Hide resolved
internal/services/v1/relationships.go Outdated Show resolved Hide resolved
@josephschorr
Copy link
Member Author

Updated. Good catch on the deletion side: it was missing handlers for the prefix filtering

@vroldanbet vroldanbet added this pull request to the merge queue Mar 13, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 13, 2024
@vroldanbet vroldanbet added this pull request to the merge queue Mar 13, 2024
Merged via the queue into authzed:main with commit 031e5b4 Mar 13, 2024
20 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Mar 13, 2024
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/datastore Affects the storage system area/dependencies Affects dependencies 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.

Remove/Delete an object and all its relations (including used as subjects) in one call
3 participants