Skip to content

Commit

Permalink
feat: cache get group by slug
Browse files Browse the repository at this point in the history
  • Loading branch information
FemiNoviaLina committed Jun 11, 2024
1 parent 54c5de2 commit b1b3fb2
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 7 deletions.
11 changes: 10 additions & 1 deletion .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,13 @@ packages:
filename: "resource_service.go"
Repository:
config:
filename: "servicedata_repository.go"
filename: "servicedata_repository.go"
github.com/goto/shield/internal/store/cache:
config:
dir: "internal/store/cache/mocks"
outpkg: "mocks"
mockname: "{{.InterfaceName}}"
interfaces:
GroupRepository:
config:
filename: "group_repository.go"
12 changes: 10 additions & 2 deletions cmd/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/goto/shield/internal/schema"
"github.com/goto/shield/internal/server"
"github.com/goto/shield/internal/store/blob"
"github.com/goto/shield/internal/store/cache"
"github.com/goto/shield/internal/store/postgres"
"github.com/goto/shield/internal/store/spicedb"
"github.com/goto/shield/pkg/db"
Expand Down Expand Up @@ -149,7 +150,7 @@ func StartServer(logger *log.Zap, cfg *config.Shield) error {
return err
}

deps, err := BuildAPIDependencies(ctx, logger, activityRepository, resourceBlobRepository, dbClient, spiceDBClient)
deps, err := BuildAPIDependencies(ctx, logger, activityRepository, resourceBlobRepository, dbClient, spiceDBClient, cfg)
if err != nil {
return err
}
Expand Down Expand Up @@ -191,7 +192,13 @@ func BuildAPIDependencies(
resourceBlobRepository *blob.ResourcesRepository,
dbc *db.Client,
sdb *spicedb.SpiceDB,
cfg *config.Shield,
) (api.Deps, error) {
cacheObj, err := cache.NewCache(cfg.App.CacheConfig)
if err != nil {
return api.Deps{}, err
}

appConfig := activity.AppConfig{Version: config.Version}
activityService := activity.NewService(appConfig, activityRepository)

Expand All @@ -212,7 +219,8 @@ func BuildAPIDependencies(
relationService := relation.NewService(logger, relationPGRepository, relationSpiceRepository, userService, activityService)

groupRepository := postgres.NewGroupRepository(dbc)
groupService := group.NewService(logger, groupRepository, relationService, userService, activityService)
cachedGroupRepository := cache.NewCachedGroupRepository(cacheObj, groupRepository)
groupService := group.NewService(logger, groupRepository, cachedGroupRepository, relationService, userService, activityService)

organizationRepository := postgres.NewOrganizationRepository(dbc)
organizationService := organization.NewService(logger, organizationRepository, relationService, userService, activityService)
Expand Down
4 changes: 4 additions & 0 deletions core/group/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ type Repository interface {
ListGroupRelations(ctx context.Context, objectId, subjectType, role string) ([]relation.RelationV2, error)
}

type CachedRepository interface {
GetBySlug(ctx context.Context, slug string) (Group, error)
}

type Group struct {
ID string
Name string
Expand Down
8 changes: 5 additions & 3 deletions core/group/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ type ActivityService interface {
type Service struct {
logger log.Logger
repository Repository
cacheRepository CachedRepository
relationService RelationService
userService UserService
activityService ActivityService
}

func NewService(logger log.Logger, repository Repository, relationService RelationService, userService UserService, activityService ActivityService) *Service {
func NewService(logger log.Logger, repository Repository, cacheRepository CachedRepository, relationService RelationService, userService UserService, activityService ActivityService) *Service {
return &Service{
logger: logger,
repository: repository,
cacheRepository: cacheRepository,
relationService: relationService,
userService: userService,
activityService: activityService,
Expand Down Expand Up @@ -86,11 +88,11 @@ func (s Service) Get(ctx context.Context, idOrSlug string) (Group, error) {
if uuid.IsValid(idOrSlug) {
return s.repository.GetByID(ctx, idOrSlug)
}
return s.repository.GetBySlug(ctx, idOrSlug)
return s.cacheRepository.GetBySlug(ctx, idOrSlug)
}

func (s Service) GetBySlug(ctx context.Context, slug string) (Group, error) {
return s.repository.GetBySlug(ctx, slug)
return s.cacheRepository.GetBySlug(ctx, slug)
}

func (s Service) GetByIDs(ctx context.Context, groupIDs []string) ([]Group, error) {
Expand Down
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/authzed/authzed-go v0.7.1-0.20221109204547-1aa903788b3b
github.com/authzed/grpcutil v0.0.0-20230908193239-4286bb1d6403
github.com/authzed/spicedb v1.15.0
github.com/dgraph-io/ristretto v0.1.1
github.com/doug-martin/goqu/v9 v9.18.0
github.com/envoyproxy/protoc-gen-validate v1.0.4
github.com/ghodss/yaml v1.0.0
Expand Down Expand Up @@ -76,6 +77,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/glamour v0.6.0 // indirect
github.com/cli/safeexec v1.0.1 // indirect
github.com/containerd/continuity v0.3.0 // indirect
Expand All @@ -84,6 +86,7 @@ require (
github.com/dlclark/regexp2 v1.9.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.14.1 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
Expand All @@ -93,6 +96,7 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/golang/glog v1.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/google/cel-go v0.13.0 // indirect
github.com/google/pprof v0.0.0-20221219190121-3cb0bae90811 // indirect
Expand Down
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM273bISc=
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw=
Expand Down Expand Up @@ -811,8 +813,12 @@ github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8=
github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA=
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dgryski/go-sip13 v0.0.0-20200911182023-62edffca9245/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw=
Expand Down Expand Up @@ -852,6 +858,7 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/doug-martin/goqu/v9 v9.18.0 h1:/6bcuEtAe6nsSMVK/M+fOiXUNfyFF3yYtE07DBPFMYY=
github.com/doug-martin/goqu/v9 v9.18.0/go.mod h1:nf0Wc2/hV3gYK9LiyqIrzBEVGlI8qW3GuDCEobC4wBQ=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
Expand Down Expand Up @@ -2509,6 +2516,7 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220908150016-7ac13a9a928d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
4 changes: 4 additions & 0 deletions internal/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package server

import (
"fmt"

"github.com/goto/shield/internal/store/cache"
)

type GRPCConfig struct {
Expand Down Expand Up @@ -63,4 +65,6 @@ type Config struct {
ServiceData ServiceDataConfig `yaml:"service_data" mapstructure:"service_data"`

PublicAPIPrefix string `yaml:"public_api_prefix" mapstructure:"public_api_prefix" default:"/shield"`

CacheConfig cache.Config `yaml:"cache" mapstructure:"cache"`
}
39 changes: 39 additions & 0 deletions internal/store/cache/cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package cache

import (
"errors"

"github.com/dgraph-io/ristretto"
)

var ErrParsing = errors.New("parsing error")

type Config struct {
NumCounters int64 `yaml:"num_counters" mapstructure:"num_counters" default:"10000000"`
MaxCost int64 `yaml:"max_cost" mapstructure:"max_cost" default:"1073741824"`
BufferItems int64 `yaml:"buffer_items" mapstructure:"buffer_items" default:"64"`
Metrics bool `yaml:"metrics" mapstructure:"metrics" default:"true"`
TTLInSeconds int `yaml:"ttl_in_seconds" mapstructure:"ttl_in_seconds" default:"3600"`
}

type Cache struct {
*ristretto.Cache
config Config
}

func NewCache(config Config) (Cache, error) {
cache, err := ristretto.NewCache(&ristretto.Config{
NumCounters: config.NumCounters,
MaxCost: config.MaxCost,
BufferItems: config.MaxCost,
Metrics: config.Metrics,
})
if err != nil {
return Cache{}, err
}

return Cache{
Cache: cache,
config: config,
}, nil
}
52 changes: 52 additions & 0 deletions internal/store/cache/group_repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package cache

import (
"context"
"fmt"
"time"

"github.com/goto/shield/core/group"
)

var keyPrefix = "group"

type GroupRepository interface {
GetBySlug(ctx context.Context, slug string) (group.Group, error)
}

type CachedGroupRepository struct {
cache Cache
repository GroupRepository
}

func NewCachedGroupRepository(cache Cache, repository GroupRepository) *CachedGroupRepository {
return &CachedGroupRepository{
cache: cache,
repository: repository,
}
}

func getKey(identifier string) string {
return fmt.Sprintf("%s:%s", keyPrefix, identifier)
}

func (r CachedGroupRepository) GetBySlug(ctx context.Context, slug string) (group.Group, error) {
key := getKey(slug)
grp, found := r.cache.Get(key)
if !found {
grp, err := r.repository.GetBySlug(ctx, slug)
if err != nil {
return group.Group{}, err
}

r.cache.SetWithTTL(key, grp, 0, time.Duration(r.cache.config.TTLInSeconds)*time.Second)
return grp, nil
}

grpParsed, ok := grp.(group.Group)
if !ok {
return group.Group{}, ErrParsing
}

return grpParsed, nil
}
Loading

0 comments on commit b1b3fb2

Please sign in to comment.