Skip to content

Commit

Permalink
relpool change + RelationId refectoring (#62)
Browse files Browse the repository at this point in the history
* convert azm to use RelationIdentifier

* update go-directory & grpc deps

* Fix: Checker.checkRelation wasn't setting the subject ID

As a result it was getting way more relations back.

* update deps

* Toggle between shared or per-call memory pool.

* Replace Cache RWMutex with an atomic pointer.

* Initialize SlicePool with given capacity

* upd [email protected]

---------

Co-authored-by: Ronen Hilewicz <[email protected]>
  • Loading branch information
gertd and ronenh authored Dec 11, 2024
1 parent db142a7 commit 58c42fb
Show file tree
Hide file tree
Showing 13 changed files with 104 additions and 118 deletions.
53 changes: 19 additions & 34 deletions cache/cache.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package cache

import (
"sync/atomic"

"github.com/aserto-dev/azm/mempool"
"github.com/aserto-dev/azm/model"
"github.com/aserto-dev/azm/model/diff"
stts "github.com/aserto-dev/azm/stats"
Expand All @@ -15,49 +18,39 @@ type (
)

type Cache struct {
model *model.Model
// mtx sync.RWMutex
// relsPool *mempool.RelationsPool
model atomic.Pointer[model.Model]
relsPool *mempool.RelationsPool
}

// New, create new model cache instance.
func New(m *model.Model) *Cache {
return &Cache{
model: m,
// mtx: sync.RWMutex{},
// relsPool: mempool.NewRelationsPool(),
cache := &Cache{
relsPool: mempool.NewRelationsPool(),
}

cache.model.Store(m)
return cache
}

// UpdateModel, swaps the cache model instance.
func (c *Cache) UpdateModel(m *model.Model) error {
// c.mtx.Lock()
// defer c.mtx.Unlock()
c.model = m
c.model.Store(m)
return nil
}

func (c *Cache) CanUpdate(other *model.Model, stats *stts.Stats) error {
// c.mtx.RLock()
// defer c.mtx.RUnlock()
return diff.CanUpdateModel(c.model, other, stats)
return diff.CanUpdateModel(c.model.Load(), other, stats)
}

// ObjectExists, checks if given object type name exists in the model cache.
func (c *Cache) ObjectExists(on ObjectName) bool {
// c.mtx.RLock()
// defer c.mtx.RUnlock()

_, ok := c.model.Objects[on]
_, ok := c.model.Load().Objects[on]
return ok
}

// RelationExists, checks if given relation type, for the given object type, exists in the model cache.
func (c *Cache) RelationExists(on ObjectName, rn RelationName) bool {
// c.mtx.RLock()
// defer c.mtx.RUnlock()

if obj, ok := c.model.Objects[on]; ok {
if obj, ok := c.model.Load().Objects[on]; ok {
_, ok := obj.Relations[rn]
return ok
}
Expand All @@ -66,27 +59,19 @@ func (c *Cache) RelationExists(on ObjectName, rn RelationName) bool {

// PermissionExists, checks if given permission, for the given object type, exists in the model cache.
func (c *Cache) PermissionExists(on ObjectName, pn RelationName) bool {
// c.mtx.RLock()
// defer c.mtx.RUnlock()

if obj, ok := c.model.Objects[on]; ok {
if obj, ok := c.model.Load().Objects[on]; ok {
_, ok := obj.Permissions[pn]
return ok
}
return false
}

func (c *Cache) Metadata() *model.Metadata {
// c.mtx.RLock()
// defer c.mtx.RUnlock()
return c.model.Metadata
return c.model.Load().Metadata
}

func (c *Cache) ValidateRelation(relation *dsc.Relation) error {
// c.mtx.RLock()
// defer c.mtx.RUnlock()

return c.model.ValidateRelation(
func (c *Cache) ValidateRelation(relation *dsc.RelationIdentifier) error {
return c.model.Load().ValidateRelation(
ObjectName(relation.ObjectType),
model.ObjectID(relation.ObjectId),
RelationName(relation.Relation),
Expand Down Expand Up @@ -123,7 +108,7 @@ func (c *Cache) AssignableRelations(on, sn ObjectName, sr ...RelationName) ([]Re
}
}

matches := lo.PickBy(c.model.Objects[on].Relations, func(rn RelationName, r *model.Relation) bool {
matches := lo.PickBy(c.model.Load().Objects[on].Relations, func(rn RelationName, r *model.Relation) bool {
for _, ref := range r.Union {
if ref.Object != sn {
// type mismatch
Expand Down
21 changes: 15 additions & 6 deletions cache/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ import (
"google.golang.org/protobuf/types/known/structpb"
)

// If true, use a shared memory pool for all requests.
// Othersise, each call gets its own pool.
const sharedPool = true

func (c *Cache) Check(req *dsr.CheckRequest, relReader graph.RelationReader) (*dsr.CheckResponse, error) {
relsPool := mempool.NewRelationsPool()
checker := graph.NewCheck(c.model, req, relReader, relsPool)
checker := graph.NewCheck(c.model.Load(), req, relReader, c.relationsPool())

ctx := pb.NewStruct()

Expand All @@ -33,12 +36,10 @@ func (c *Cache) GetGraph(req *dsr.GetGraphRequest, relReader graph.RelationReade
err error
)

relsPool := mempool.NewRelationsPool()

if req.ObjectId == "" {
search, err = graph.NewObjectSearch(c.model, req, relReader, relsPool)
search, err = graph.NewObjectSearch(c.model.Load(), req, relReader, c.relationsPool())
} else {
search, err = graph.NewSubjectSearch(c.model, req, relReader, relsPool)
search, err = graph.NewSubjectSearch(c.model.Load(), req, relReader, c.relationsPool())
}

if err != nil {
Expand All @@ -47,3 +48,11 @@ func (c *Cache) GetGraph(req *dsr.GetGraphRequest, relReader graph.RelationReade

return search.Search()
}

func (c *Cache) relationsPool() *mempool.RelationsPool {
if sharedPool {
return c.relsPool
}

return mempool.NewRelationsPool()
}
26 changes: 13 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
module github.com/aserto-dev/azm

go 1.22.9
go 1.22.10

toolchain go1.23.3
toolchain go1.23.4

replace github.com/aserto-dev/go-directory => ../go-directory
// replace github.com/aserto-dev/go-directory => ../go-directory

require (
github.com/antlr4-go/antlr/v4 v4.13.1
github.com/aserto-dev/errors v0.0.11
github.com/aserto-dev/go-directory v0.33.2-0.20241209182914-962e2284a774
github.com/deckarep/golang-set/v2 v2.6.0
github.com/aserto-dev/go-directory v0.33.2
github.com/deckarep/golang-set/v2 v2.7.0
github.com/hashicorp/go-multierror v1.1.1
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/nsf/jsondiff v0.0.0-20230430225905-43f6cf3098c1
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.33.0
github.com/samber/lo v1.47.0
github.com/stretchr/testify v1.10.0
google.golang.org/grpc v1.68.0
google.golang.org/grpc v1.68.1
google.golang.org/protobuf v1.35.2
gopkg.in/yaml.v3 v3.0.1
)

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 // indirect
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/net v0.31.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/text v0.20.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/net v0.32.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect
)
38 changes: 20 additions & 18 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1 h1:7QIeAuTdLp173vC/9JojRMDFcpmqtoYrxPmvdHAOynw=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20240920164238-5a7b106cbb87.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1 h1:jLd96rDDNJ+zIJxvV/L855VEtrjR0G4aePVDlCpf6kw=
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.35.2-20241127180247-a33202765966.1/go.mod h1:mnHCFccv4HwuIAOHNGdiIc5ZYbBCvbTWZcodLN5wITI=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
github.com/aserto-dev/errors v0.0.11 h1:CXo+Uwmh09doG2HvL1SC8Fnne8f9VPrGyEQPtogAfyY=
github.com/aserto-dev/errors v0.0.11/go.mod h1:T1YQOtcxpgBriPTn5HXJkD/QukYz5YojYOIzGMo0ybM=
github.com/aserto-dev/go-directory v0.33.2 h1:QJwzSmfxJ7EG0RzWsgu7In5cAeGtZURZklSsHhMOFh8=
github.com/aserto-dev/go-directory v0.33.2/go.mod h1:gK239V0htJtp0/BwvbTrYv/XIphoK/AugP8sw3m8B0s=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/deckarep/golang-set/v2 v2.7.0 h1:gIloKvD7yH2oip4VLhsv3JyLLFnC0Y2mlusgcvJYW5k=
github.com/deckarep/golang-set/v2 v2.7.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
Expand Down Expand Up @@ -50,23 +52,23 @@ github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 h1:pgr/4QbFyktUv9CtQ/Fq4gzEE6/Xs7iCXbktaGzLHbQ=
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697/go.mod h1:+D9ySVjN8nY8YCVjc5O7PZDIdZporIDY3KaGfJunh88=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 h1:LWZqQOEjDyONlF1H6afSWpAL/znlREo2tHfLoe+8LMA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
8 changes: 5 additions & 3 deletions graph/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,16 @@ func (c *Checker) checkRelation(params *relation) (checkStatus, error) {
for _, step := range steps {
*relsPtr = (*relsPtr)[:0]

req := &dsc.Relation{
req := &dsc.RelationIdentifier{
ObjectType: params.ot.String(),
ObjectId: params.oid.String(),
Relation: params.rel.String(),
SubjectType: step.Object.String(),
}

switch {
case step.IsDirect():
req.SubjectId = params.sid.String()
case step.IsWildcard():
req.SubjectId = "*"
case step.IsSubject():
Expand Down Expand Up @@ -198,7 +200,7 @@ func (c *Checker) checkPermission(params *relation) (checkStatus, error) {

func (c *Checker) expandTerm(pt *model.PermissionTerm, params *relation) (relations, error) {
if pt.IsArrow() {
query := &dsc.Relation{
query := &dsc.RelationIdentifier{
ObjectType: params.ot.String(),
ObjectId: params.oid.String(),
Relation: pt.Base.String(),
Expand All @@ -212,7 +214,7 @@ func (c *Checker) expandTerm(pt *model.PermissionTerm, params *relation) (relati
return relations{}, err
}

expanded := lo.Map(*relsPtr, func(rel *dsc.Relation, _ int) *relation {
expanded := lo.Map(*relsPtr, func(rel *dsc.RelationIdentifier, _ int) *relation {
return &relation{
ot: model.ObjectName(rel.SubjectType),
oid: ObjectID(rel.SubjectId),
Expand Down
4 changes: 2 additions & 2 deletions graph/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,15 @@ func wildcardParams(params *relation) *relation {
}

func invertedRelationReader(m *model.Model, reader RelationReader) RelationReader {
return func(r *dsc.Relation, relPool MessagePool[*dsc.Relation], out *Relations) error {
return func(r *dsc.RelationIdentifier, relPool MessagePool[*dsc.RelationIdentifier], out *Relations) error {
ir := uninvertRelation(m, relationFromProto(r))
if err := reader(ir.asProto(), relPool, out); err != nil {
return err
}

res := *out
for i, r := range res {
res[i] = &dsc.Relation{
res[i] = &dsc.RelationIdentifier{
ObjectType: r.SubjectType,
ObjectId: r.SubjectId,
Relation: r.Relation,
Expand Down
8 changes: 4 additions & 4 deletions graph/relation.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type relation struct {

type relations []*relation

// converts a dsc.Relation to a relation.
func relationFromProto(rel *dsc.Relation) *relation {
// converts a dsc.RelationIdentifier to a relation.
func relationFromProto(rel *dsc.RelationIdentifier) *relation {
return &relation{
ot: model.ObjectName(rel.ObjectType),
oid: ObjectID(rel.ObjectId),
Expand All @@ -31,8 +31,8 @@ func relationFromProto(rel *dsc.Relation) *relation {
}
}

func (r *relation) asProto() *dsc.Relation {
return &dsc.Relation{
func (r *relation) asProto() *dsc.RelationIdentifier {
return &dsc.RelationIdentifier{
ObjectType: string(r.ot),
ObjectId: string(r.oid),
Relation: string(r.rel),
Expand Down
8 changes: 3 additions & 5 deletions graph/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

type (
ObjectID = model.ObjectID
Relations = []*dsc.Relation
Relations = []*dsc.RelationIdentifier

searchPath relations

Expand All @@ -34,10 +34,10 @@ type MessagePool[T any] interface {
Put(T)
}

type RelationPool = MessagePool[*dsc.Relation]
type RelationPool = MessagePool[*dsc.RelationIdentifier]

// RelationReader retrieves relations that match the given filter.
type RelationReader func(*dsc.Relation, RelationPool, *Relations) error
type RelationReader func(*dsc.RelationIdentifier, RelationPool, *Relations) error

// Objects returns the objects from the search results.
func (r searchResults) Objects() []*dsc.ObjectIdentifier {
Expand Down Expand Up @@ -132,7 +132,6 @@ func searchParams(req *dsr.GetGraphRequest) *relation {
sid: ObjectID(req.SubjectId),
srel: model.RelationName(req.SubjectRelation),
}

}

type searchCall struct {
Expand Down Expand Up @@ -169,7 +168,6 @@ func (m *searchMemo) MarkVisited(params *relation) searchStatus {
func (m *searchMemo) MarkComplete(params *relation, results searchResults) {
m.visited[*params] = results
m.trace(params, searchStatusComplete)

}

func (m *searchMemo) Status(params *relation) searchStatus {
Expand Down
Loading

0 comments on commit 58c42fb

Please sign in to comment.