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

feat: batch check relations #1521

Merged
merged 16 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/status/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestStatusCmd(t *testing.T) {
defer cancel()

stdErr := cmdx.ExecExpectedErrCtx(ctx, t, newStatusCmd(), "--"+FlagEndpoint, string(serverType), "--"+ts.FlagRemote, ts.Addr[:len(ts.Addr)-1])
assert.Equal(t, "context deadline exceeded", stdErr)
assert.Contains(t, stdErr, "context deadline exceeded")
hperl marked this conversation as resolved.
Show resolved Hide resolved
})

t.Run("case=noblock", func(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions embedx/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@
"description": "The global maximum width on all read operations. Note that this does not affect how deeply nested the tuples can be. This value can be decreased for a request by a value specified on the request, only if the request-specific value is greater than 1 and less than the global maximum width.",
"minimum": 1,
"maximum": 65535
},
"max_batch_check_size": {
"type": "integer",
"default": 10,
"title": "Maximum batch check size",
"description": "The maximum number of tuples that will be accepted by the batch check endpoint.",
"minimum": 1,
"maximum": 65535
}
},
"additionalProperties": false
Expand Down
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ require (
go.opentelemetry.io/otel/trace v1.21.0
go.uber.org/goleak v1.3.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/oauth2 v0.14.0
golang.org/x/oauth2 v0.16.0
golang.org/x/sync v0.7.0
google.golang.org/grpc v1.59.0
google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.33.0
)

Expand Down Expand Up @@ -97,7 +97,7 @@ require (
github.com/goccy/go-yaml v1.11.2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/glog v1.1.2 // indirect
github.com/golang/glog v1.2.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
Expand Down Expand Up @@ -192,9 +192,9 @@ require (
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
32 changes: 16 additions & 16 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go/v2 v2.3.5 h1:Khtm8K6fTTz/ZCWPzU9Ne3aOW9VyAnj4qIPCJgKtwK0=
Expand Down Expand Up @@ -121,8 +121,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc=
github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
Expand Down Expand Up @@ -212,8 +212,8 @@ github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo=
github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ=
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down Expand Up @@ -767,8 +767,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0=
golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
Expand Down Expand Up @@ -992,12 +992,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
Expand All @@ -1014,8 +1014,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/grpc/examples v0.0.0-20210304020650-930c79186c99 h1:qA8rMbz1wQ4DOFfM2ouD29DG9aHWBm6ZOy9BGxiUMmY=
google.golang.org/grpc/examples v0.0.0-20210304020650-930c79186c99/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
Expand Down
3 changes: 0 additions & 3 deletions internal/check/checkgroup/membership_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 48 additions & 2 deletions internal/check/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

import (
"context"
"sync"

"github.com/pkg/errors"
"go.opentelemetry.io/otel/trace"
"golang.org/x/sync/semaphore"

"github.com/ory/herodot"
"github.com/ory/x/otelx"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/trace"

"github.com/ory/keto/x/events"

Expand All @@ -34,6 +36,7 @@
}
EngineDependencies interface {
relationtuple.ManagerProvider
relationtuple.MapperProvider
persistence.Provider
config.Provider
x.LoggerProvider
Expand Down Expand Up @@ -264,3 +267,46 @@
}
return namespace.ASTRelationFor(ctx, namespaceManager, r.Namespace, r.Relation)
}

// BatchCheck makes parallelized check requests for tuples. The check results are returned as slice, where the
// result index matches the tuple index of the incoming tuples array.
//
// parallelizationFactor is the max the number of checks that can happen in parallel.
func (e *Engine) BatchCheck(ctx context.Context,
tuples []*ketoapi.RelationTuple,
maxDepth, parallelizationFactor int) ([]checkgroup.Result, error) {

if parallelizationFactor <= 0 {
return nil, errors.New("invalid parallelization factor")
}

wg := &sync.WaitGroup{}
sem := semaphore.NewWeighted(int64(parallelizationFactor))

mapper := e.d.ReadOnlyMapper()
results := make([]checkgroup.Result, len(tuples))
for outerIndex, outerTuple := range tuples {
sem.Acquire(context.Background(), 1) // Pass in background context to guarantee this won't return an error

Check failure on line 289 in internal/check/engine.go

View workflow job for this annotation

GitHub Actions / Run lints and checks

Error return value of `sem.Acquire` is not checked (errcheck)
patrickduffy95 marked this conversation as resolved.
Show resolved Hide resolved
wg.Add(1)
go func(i int, tuple *ketoapi.RelationTuple) {
defer func() {
wg.Done()
sem.Release(1)
}()

internalTuple, err := mapper.FromTuple(ctx, tuple)
if err != nil {
results[i] = checkgroup.Result{
Membership: checkgroup.MembershipUnknown,
Err: err,
}
} else {
results[i] = e.CheckRelationTuple(ctx, internalTuple[0], maxDepth)
}
}(outerIndex, outerTuple)
}

wg.Wait()

return results, nil
}
114 changes: 114 additions & 0 deletions internal/check/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import (
"testing"

"github.com/gofrs/uuid"
"github.com/ory/herodot"
"github.com/ory/x/pointerx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/ory/keto/internal/check"
"github.com/ory/keto/internal/check/checkgroup"
"github.com/ory/keto/internal/driver"
"github.com/ory/keto/internal/driver/config"
"github.com/ory/keto/internal/namespace"
Expand All @@ -27,6 +30,7 @@ type configProvider = config.Provider
// deps are defined to capture engine dependencies in a single struct
type deps struct {
*relationtuple.ManagerWrapper // managerProvider
relationtuple.MapperProvider
persistence.Provider
configProvider
x.LoggerProvider
Expand All @@ -41,6 +45,7 @@ func newDepsProvider(t testing.TB, namespaces []*namespace.Namespace, pageOpts .

return &deps{
ManagerWrapper: mr,
MapperProvider: reg,
Provider: reg,
configProvider: reg,
LoggerProvider: reg,
Expand Down Expand Up @@ -576,4 +581,113 @@ func TestEngine(t *testing.T) {
assert.True(t, res)
}
})

t.Run("case=batch check", func(t *testing.T) {
reg := newDepsProvider(t, []*namespace.Namespace{
{Name: "test"},
})

relationtuple.MapAndWriteTuples(t, reg, &ketoapi.RelationTuple{
Namespace: "test",
Object: "object",
Relation: "admin",
SubjectID: pointerx.Ptr("user"),
},
&ketoapi.RelationTuple{
Namespace: "test",
Object: "object",
Relation: "owner",
SubjectSet: &ketoapi.SubjectSet{
Namespace: "test",
Object: "object",
Relation: "admin",
},
},
&ketoapi.RelationTuple{
Namespace: "test",
Object: "object",
Relation: "access",
SubjectSet: &ketoapi.SubjectSet{
Namespace: "test",
Object: "object",
Relation: "owner",
},
})

e := check.NewEngine(reg)

targetTuples := []*ketoapi.RelationTuple{
{ // direct relation
Namespace: "test",
Object: "object",
Relation: "admin",
SubjectID: pointerx.Ptr("user"),
},
{ // indirect relation
Namespace: "test",
Object: "object",
Relation: "owner",
SubjectID: pointerx.Ptr("user"),
},
{ // indirect relation, greater than max depth
Namespace: "test",
Object: "object",
Relation: "access",
SubjectID: pointerx.Ptr("user"),
},
{ // non-existent namespace
Namespace: "test2",
Object: "object",
Relation: "admin",
SubjectID: pointerx.Ptr("user"),
},
{ // unknown subject
Namespace: "test",
Object: "object",
Relation: "admin",
SubjectID: pointerx.Ptr("user2"),
},
{ // relation via subject set
Namespace: "test",
Object: "object",
Relation: "access",
SubjectSet: &ketoapi.SubjectSet{
Namespace: "test",
Object: "object",
Relation: "owner",
},
},
}

// Batch check with low max depth
results, err := e.BatchCheck(ctx, targetTuples, 2, 5)
require.NoError(t, err)

require.Equal(t, checkgroup.IsMember, results[0].Membership)
require.NoError(t, results[0].Err)
require.Equal(t, checkgroup.IsMember, results[1].Membership)
require.NoError(t, results[1].Err)
require.Equal(t, checkgroup.NotMember, results[2].Membership)
require.NoError(t, results[2].Err)
require.Equal(t, checkgroup.MembershipUnknown, results[3].Membership)
require.EqualError(t, results[3].Err, herodot.ErrNotFound.Error())
require.Equal(t, checkgroup.NotMember, results[4].Membership)
require.NoError(t, results[4].Err)
require.Equal(t, checkgroup.IsMember, results[5].Membership)
require.NoError(t, results[5].Err)

// Check with higher max depth and verify the third tuple is now shown as a member
results, err = e.BatchCheck(ctx, targetTuples, 3, 5)
require.NoError(t, err)
require.Equal(t, checkgroup.IsMember, results[2].Membership)

// Check success with no parallelization
noParallelizationResults, err := e.BatchCheck(ctx, targetTuples, 3, 1)
require.NoError(t, err)
require.Equal(t, results, noParallelizationResults)

// Attempt with an invalid parallelization factor
_, err = e.BatchCheck(ctx, targetTuples, 3, 0)
require.EqualError(t, err, "invalid parallelization factor")
})
}
Loading
Loading