Skip to content

Commit

Permalink
Add subject filters in schema relation delete to force use of the index
Browse files Browse the repository at this point in the history
This should allow for much faster queries under the transaction. We
observed some customers reporting timeouts when writting a new
schema and dropping a relation because it ended up in full table
scans.
  • Loading branch information
josephschorr authored and vroldanbet committed Nov 18, 2024
1 parent 4262bfd commit 132ed3b
Show file tree
Hide file tree
Showing 2 changed files with 351 additions and 58 deletions.
42 changes: 39 additions & 3 deletions internal/services/shared/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,46 @@ func sanityCheckNamespaceChanges(
for _, delta := range diff.Deltas() {
switch delta.Type {
case nsdiff.RemovedRelation:
// NOTE: We add the subject filters here to ensure the reverse relationship index is used
// by the datastores. As there is no index that has {namespace, relation} directly, but there
// *is* an index that has {subject_namespace, subject_relation, namespace, relation}, we can
// force the datastore to use the reverse index by adding the subject filters.
var previousRelation *core.Relation
for _, relation := range existing.Relation {
if relation.Name == delta.RelationName {
previousRelation = relation
break
}
}

if previousRelation == nil {
return nil, spiceerrors.MustBugf("relation `%s` not found in existing namespace definition", delta.RelationName)
}

subjectSelectors := make([]datastore.SubjectsSelector, 0, len(previousRelation.TypeInformation.AllowedDirectRelations))
for _, allowedType := range previousRelation.TypeInformation.AllowedDirectRelations {
if allowedType.GetRelation() == datastore.Ellipsis {
subjectSelectors = append(subjectSelectors, datastore.SubjectsSelector{
OptionalSubjectType: allowedType.Namespace,
RelationFilter: datastore.SubjectRelationFilter{
IncludeEllipsisRelation: true,
},
})
} else {
subjectSelectors = append(subjectSelectors, datastore.SubjectsSelector{
OptionalSubjectType: allowedType.Namespace,
RelationFilter: datastore.SubjectRelationFilter{
NonEllipsisRelation: allowedType.GetRelation(),
},
})
}
}

qy, qyErr := rwt.QueryRelationships(ctx, datastore.RelationshipsFilter{
OptionalResourceType: nsdef.Name,
OptionalResourceRelation: delta.RelationName,
})
OptionalResourceType: nsdef.Name,
OptionalResourceRelation: delta.RelationName,
OptionalSubjectsSelectors: subjectSelectors,
}, options.WithLimit(options.LimitOne))

err = errorIfTupleIteratorReturnsTuples(
ctx,
Expand Down
Loading

0 comments on commit 132ed3b

Please sign in to comment.