Skip to content

Commit

Permalink
Merge branch 'feat/userset-rewrites' of github.com:ory/keto into feat…
Browse files Browse the repository at this point in the history
…/userset-rewrites
  • Loading branch information
hperl committed Aug 17, 2022
2 parents b47f028 + 893dd21 commit 2cd5de6
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 0 deletions.
126 changes: 126 additions & 0 deletions internal/check/bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package check_test

import (
"context"
"fmt"
"testing"

"github.com/sirupsen/logrus"
"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/config"
"github.com/ory/keto/internal/namespace"
"github.com/ory/keto/internal/namespace/ast"
)

func wideNamespace(width int) *namespace.Namespace {
wideNS := &namespace.Namespace{
Name: fmt.Sprintf("%d_wide", width),
Relations: []ast.Relation{{Name: "editor"}},
}
viewerRelation := &ast.Relation{
Name: "viewer",
SubjectSetRewrite: &ast.SubjectSetRewrite{
Operation: ast.OperatorOr,
Children: ast.Children{},
},
}
for i := 0; i < width; i++ {
relation := fmt.Sprintf("relation-%d", i)
viewerRelation.SubjectSetRewrite.Children = append(
viewerRelation.SubjectSetRewrite.Children,
&ast.ComputedSubjectSet{Relation: relation},
)
wideNS.Relations = append(wideNS.Relations, ast.Relation{Name: relation})
}
viewerRelation.SubjectSetRewrite.Children = append(
viewerRelation.SubjectSetRewrite.Children,
&ast.ComputedSubjectSet{Relation: "editor"},
)
wideNS.Relations = append(wideNS.Relations, *viewerRelation)

return wideNS
}

func BenchmarkCheckEngine(b *testing.B) {
ctx := context.Background()
var (
depths = []int{2, 4, 8, 16, 32}
widths = []int{10, 20, 40, 80, 100}
maxDepth = depths[len(depths)-1]
)

var namespaces = []*namespace.Namespace{
{Name: "deep",
Relations: []ast.Relation{
{Name: "owner"},
{Name: "editor",
SubjectSetRewrite: &ast.SubjectSetRewrite{
Children: ast.Children{&ast.ComputedSubjectSet{
Relation: "owner"}}}},
{Name: "viewer",
SubjectSetRewrite: &ast.SubjectSetRewrite{
Children: ast.Children{
&ast.ComputedSubjectSet{
Relation: "editor"},
&ast.TupleToSubjectSet{
Relation: "parent",
ComputedSubjectSetRelation: "viewer"}}}},
}},
}

reg := newDepsProvider(b, namespaces)
reg.Logger().Logger.SetLevel(logrus.InfoLevel)

tuples := []string{
"deep:deep_file#parent@deep:folder_1#...",
}
for i := 1; i < maxDepth; i++ {
tuples = append(tuples, fmt.Sprintf("deep:folder_%d#parent@deep:folder_%d#...", i, i+1))
}
for _, d := range depths {
tuples = append(tuples, fmt.Sprintf("deep:folder_%d#owner@user_%d", d, d))
}
for _, w := range widths {
namespaces = append(namespaces, wideNamespace(w))
tuples = append(tuples, fmt.Sprintf("%d-wide:wide_file#editor@user", w))
}
insertFixtures(b, reg.RelationTupleManager(), tuples)

require.NoError(b, reg.Config(ctx).Set(config.KeyLimitMaxReadDepth, 100*maxDepth))
e := check.NewEngine(reg)

b.ResetTimer()
b.Run("case=deep tree", func(b *testing.B) {
for _, depth := range depths {
b.Run(fmt.Sprintf("depth=%03d", depth), func(b *testing.B) {
for i := 0; i < b.N; i++ {
rt := tupleFromString(b, fmt.Sprintf("deep:deep_file#viewer@user_%d", depth))
res := e.CheckRelationTuple(ctx, rt, 2*depth)
assert.NoError(b, res.Err)
if res.Membership != checkgroup.IsMember {
b.Error("user should be able to view 'deep_file'")
}
}
})
}
})

b.Run("case=wide tree", func(b *testing.B) {
for _, width := range widths {
b.Run(fmt.Sprintf("width=%03d", width), func(b *testing.B) {
for i := 0; i < b.N; i++ {
rt := tupleFromString(b, fmt.Sprintf("%d-wide:wide_file#editor@user", width))
res := e.CheckRelationTuple(ctx, rt, 2*width)
assert.NoError(b, res.Err)
if res.Membership != checkgroup.IsMember {
b.Error("user should be able to view 'wide_file'")
}
}
})
}
})
}
4 changes: 4 additions & 0 deletions internal/check/checkgroup/concurrent_checkgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type concurrentCheckgroup struct {
// derived from the context.
pool Pool

singleWorkerPool Pool

// subcheckCtx is the context used for the subchecks.
subcheckCtx context.Context

Expand Down Expand Up @@ -50,6 +52,7 @@ func NewConcurrent(ctx context.Context) Checkgroup {
addCheckCh: make(chan CheckFunc),
}
g.subcheckCtx, g.cancel = context.WithCancel(g.ctx)
g.singleWorkerPool = NewPool(WithWorkers(1), WithContext(g.subcheckCtx))
g.startConsumer()
return g
}
Expand Down Expand Up @@ -89,6 +92,7 @@ func (g *concurrentCheckgroup) startConsumer() {
continue
}
totalChecks++
go f(g.subcheckCtx, subcheckCh)

case <-g.finalizeCh:
if finalizing {
Expand Down
4 changes: 4 additions & 0 deletions internal/check/checkgroup/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ type (
// only be run if there is a free worker available in the pool, thus
// limiting the concurrent workloads in flight.
Add(check func())

// TryAdd tries to add the check function if the pool has capacity.
// Otherwise, it returns false and does not add the check.
TryAdd(check func()) bool
}

workerPool struct {
Expand Down
14 changes: 14 additions & 0 deletions internal/check/checkgroup/workerpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,21 @@ func (p *workerPool) Add(check func()) {
p.jobs <- check
}

func (p *workerPool) TryAdd(check func()) bool {
select {
case p.jobs <- check:
return true
default:
return false
}
}

// Add on a limitless pool just runs the function in a go routine.
func (p *limitlessPool) Add(check func()) {
go check()
}

func (p *limitlessPool) TryAdd(check func()) bool {
p.Add(check)
return true
}
5 changes: 5 additions & 0 deletions internal/check/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ func NewEngine(d EngineDependencies, opts ...EngineOpt) *Engine {
for _, opt := range opts {
opt(e)
}
if e.pool == nil {
e.pool = checkgroup.NewPool(
checkgroup.WithWorkers(e.d.Config(context.Background()).MaxParallelChecks()),
)
}

return e
}
Expand Down

0 comments on commit 2cd5de6

Please sign in to comment.