Proxy accesstoken cache store (#5829)
* refactor middleware options Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * use ocmemstore micro store implementaiton for token cache Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * refactor ocis store options, support redis sentinel Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * align cache configuration Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * database and tabe are used to build prefixes for inmemory stores Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * add global persistent store options to userlog config Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * log cache errors but continue Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * drup unnecessary type conversion Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * Better description for the default userinfo ttl Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * use global cache options for even more caches Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * don't log userinfo cache misses Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * default to stock memory store Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * use correct mem store typo string Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * split cache options, doc cleanup Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * mint and write userinfo to cache async Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * use hashed token as key Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * go mod tidy Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * update docs Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * update cache store naming Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * bring back depreceted ocis-pkg/store package for backwards compatability Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * update changelog Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * Apply suggestions from code review Co-authored-by: kobergj <jkoberg@owncloud.com> * revert ocis-pkg/cache to store rename Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> * add waiting for each step 50 milliseconds * starlack check --------- Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de> Co-authored-by: kobergj <jkoberg@owncloud.com> Co-authored-by: Viktor Scharf <scharf.vi@gmail.com>
This commit is contained in:
co-authored by
kobergj
Viktor Scharf
parent
688d07e297
commit
6bec87f582
@@ -1,36 +0,0 @@
|
||||
package roles
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/sync"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
)
|
||||
|
||||
// cache is a cache implementation for roles, keyed by roleIDs.
|
||||
type cache struct {
|
||||
sc sync.Cache
|
||||
ttl time.Duration
|
||||
}
|
||||
|
||||
// newCache returns a new instance of Cache.
|
||||
func newCache(capacity int, ttl time.Duration) cache {
|
||||
return cache{
|
||||
ttl: ttl,
|
||||
sc: sync.NewCache(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
// get gets a role-bundle by a given `roleID`.
|
||||
func (c *cache) get(roleID string) *settingsmsg.Bundle {
|
||||
if ce := c.sc.Load(roleID); ce != nil {
|
||||
return ce.V.(*settingsmsg.Bundle)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// set sets a roleID / role-bundle.
|
||||
func (c *cache) set(roleID string, value *settingsmsg.Bundle) {
|
||||
c.sc.Store(roleID, value, time.Now().Add(c.ttl))
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package roles
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func cacheRunner(size int, ttl time.Duration) (*cache, func(f func(v string))) {
|
||||
c := newCache(size, ttl)
|
||||
run := func(f func(v string)) {
|
||||
wg := sync.WaitGroup{}
|
||||
for i := 0; i < size; i++ {
|
||||
wg.Add(1)
|
||||
go func(i int) {
|
||||
f(strconv.Itoa(i))
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
return &c, run
|
||||
}
|
||||
|
||||
func BenchmarkCache(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
size := 1024
|
||||
c, cr := cacheRunner(size, 100*time.Millisecond)
|
||||
|
||||
cr(func(v string) { c.set(v, &settingsmsg.Bundle{}) })
|
||||
cr(func(v string) { c.get(v) })
|
||||
}
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
size := 1024
|
||||
ttl := 100 * time.Millisecond
|
||||
c, cr := cacheRunner(size, ttl)
|
||||
|
||||
cr(func(v string) {
|
||||
c.set(v, &settingsmsg.Bundle{Id: v})
|
||||
})
|
||||
|
||||
assert.Equal(t, "50", c.get("50").Id, "it returns the right bundle")
|
||||
assert.Nil(t, c.get("unknown"), "unknown bundle ist nil")
|
||||
|
||||
time.Sleep(ttl + 1)
|
||||
// roles cache has no access to evict, adding new items triggers a cleanup
|
||||
c.set("evict", nil)
|
||||
assert.Nil(t, c.get("50"), "old bundles get removed")
|
||||
}
|
||||
+11
-11
@@ -5,23 +5,23 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ocisstore "github.com/owncloud/ocis/v2/ocis-pkg/store"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/store"
|
||||
settingsmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/settings/v0"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"go-micro.dev/v4/store"
|
||||
microstore "go-micro.dev/v4/store"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
const (
|
||||
cacheDatabase = "ocis-pkg"
|
||||
cacheTableName = "ocis-pkg/roles"
|
||||
cacheTableName = "roles"
|
||||
cacheTTL = time.Hour
|
||||
)
|
||||
|
||||
// Manager manages a cache of roles by fetching unknown roles from the settings.RoleService.
|
||||
type Manager struct {
|
||||
logger log.Logger
|
||||
cache store.Store
|
||||
roleCache microstore.Store
|
||||
roleService settingssvc.RoleService
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ type Manager struct {
|
||||
func NewManager(o ...Option) Manager {
|
||||
opts := newOptions(o...)
|
||||
|
||||
nStore := ocisstore.Create(opts.storeOptions...)
|
||||
nStore := store.Create(opts.storeOptions...)
|
||||
return Manager{
|
||||
cache: nStore,
|
||||
roleCache: nStore,
|
||||
roleService: opts.roleService,
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (m *Manager) List(ctx context.Context, roleIDs []string) []*settingsmsg.Bun
|
||||
result := make([]*settingsmsg.Bundle, 0)
|
||||
lookup := make([]string, 0)
|
||||
for _, roleID := range roleIDs {
|
||||
if records, err := m.cache.Read(roleID, store.ReadFrom(cacheDatabase, cacheTableName)); err != nil {
|
||||
if records, err := m.roleCache.Read(roleID, microstore.ReadFrom(cacheDatabase, cacheTableName)); err != nil {
|
||||
lookup = append(lookup, roleID)
|
||||
} else {
|
||||
role := &settingsmsg.Bundle{}
|
||||
@@ -77,15 +77,15 @@ func (m *Manager) List(ctx context.Context, roleIDs []string) []*settingsmsg.Bun
|
||||
}
|
||||
for _, role := range res.Bundles {
|
||||
jsonbytes, _ := protojson.Marshal(role)
|
||||
record := &store.Record{
|
||||
record := µstore.Record{
|
||||
Key: role.Id,
|
||||
Value: jsonbytes,
|
||||
Expiry: cacheTTL,
|
||||
}
|
||||
err := m.cache.Write(
|
||||
err := m.roleCache.Write(
|
||||
record,
|
||||
store.WriteTo(cacheDatabase, cacheTableName),
|
||||
store.WriteTTL(cacheTTL),
|
||||
microstore.WriteTo(cacheDatabase, cacheTableName),
|
||||
microstore.WriteTTL(cacheTTL),
|
||||
)
|
||||
if err != nil {
|
||||
m.logger.Debug().Err(err).Msg("failed to cache roles")
|
||||
|
||||
@@ -2,13 +2,13 @@ package roles
|
||||
|
||||
import (
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
ocisstore "github.com/owncloud/ocis/v2/ocis-pkg/store"
|
||||
settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0"
|
||||
"go-micro.dev/v4/store"
|
||||
)
|
||||
|
||||
// Options are all the possible options.
|
||||
type Options struct {
|
||||
storeOptions []ocisstore.Option
|
||||
storeOptions []store.Option
|
||||
logger log.Logger
|
||||
roleService settingssvc.RoleService
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func RoleService(rs settingssvc.RoleService) Option {
|
||||
}
|
||||
|
||||
// StoreOptions are the options for the store
|
||||
func StoreOptions(storeOpts []ocisstore.Option) Option {
|
||||
func StoreOptions(storeOpts []store.Option) Option {
|
||||
return func(o *Options) {
|
||||
o.storeOptions = storeOpts
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user