feat: add support for bulk resource ID filtering in ReadRelationships
This PR introduces optional_resource_ids field to RelationshipFilter, enabling bulk relationship reads in a single API call.
After: Single bulk call
const namespaces = await spicedb.readRelationships({
relationship_filter: {
resource_type: "document",
optional_resource_ids: ["DocumentA", "DocumentB", "DocumentC"],
optional_relation: "parent"
}
});
Implementation Details
Changes Made
-
Validation Layer: Added counter-based mutual exclusion validation ensuring only one of
optional_resource_id,optional_resource_id_prefix, oroptional_resource_idscan be specified -
Filter Conversion: Updated
RelationshipsFilterFromPublicFilter()to handle the new bulk field and convert it to internalOptionalResourceIds []string -
Database Optimization: Leverages existing
FilterToResourceIDs()function that generates optimizedINclause queries -
Comprehensive Testing: Added test cases covering single IDs, multiple IDs, error scenarios, and mutual exclusion validation
Compatibility
- ✅ Backward Compatible: Existing
optional_resource_idusage unchanged - ✅ All Datastores: Works universally across PostgreSQL, MySQL, CockroachDB, Spanner, and MemDB
- ✅ Validation: Prevents conflicting field usage with clear error messages
Testing
go test ./pkg/datastore -v -run TestRelationshipsFilterFromPublicFilter
go test ./internal/services/v1 -v -run TestValidateRelationshipsFilter
Related Issues
Addresses the bulk relationship reading capability discussed in https://github.com/authzed/spicedb/issues/2160
Checklist
- [x] Implementation follows existing patterns
- [x] Counter-based validation prevents field conflicts
- [x] Comprehensive test coverage added
- [x] Works across all supported datastores
- [x] Maintains backward compatibility
@THE-BRAHMA Is the intention to add support to the API layer itself as well?
Yes, the API layer already supports it! No new API endpoint needed - the existing one handles both single and bulk resource IDs. Clients can now pass either a optional_resource_id or optional_resource_ids in the same RelationshipFilter Cc @josephschorr
api-level support added here: https://github.com/authzed/api/pull/145
@josephschorr & @tstirrat15 Let me know if there is any improvement needed in this PR or is there a better way to solve this task.