Files
opencloud/ocis-pkg/store/cache.go
Jörn Friedrich Dreyer 6bec87f582 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>
2023-03-22 15:21:57 +01:00

119 lines
3.3 KiB
Go

package store
import (
"context"
"strings"
"time"
natsjs "github.com/go-micro/plugins/v4/store/nats-js"
"github.com/go-micro/plugins/v4/store/redis"
redisopts "github.com/go-redis/redis/v8"
"github.com/nats-io/nats.go"
"github.com/owncloud/ocis/v2/ocis-pkg/store/etcd"
"github.com/owncloud/ocis/v2/ocis-pkg/store/memory"
"go-micro.dev/v4/logger"
"go-micro.dev/v4/store"
)
var ocMemStore *store.Store
const (
TypeMemory = "memory"
TypeNoop = "noop"
TypeEtcd = "etcd"
TypeRedis = "redis"
TypeRedisSentinel = "redis-sentinel"
TypeOCMem = "ocmem"
TypeNatsJS = "nats-js"
)
// Create returns a configured key-value micro store
//
// Each microservice (or whatever piece is using the store) should use the
// options available in the interface's operations to choose the right database
// and table to prevent collisions with other microservices.
// Recommended approach is to use "services" or "ocis-pkg" for the database,
// and "services/<service-name>/" or "ocis-pkg/<pkg>/" for the package name.
func Create(opts ...store.Option) store.Store {
options := &store.Options{
Context: context.Background(),
}
for _, o := range opts {
o(options)
}
storeType, _ := options.Context.Value(typeContextKey{}).(string)
switch storeType {
case TypeNoop:
return store.NewNoopStore(opts...)
case TypeEtcd:
return etcd.NewEtcdStore(opts...)
case TypeRedis:
// FIXME redis plugin does not support redis cluster or ring -> needs upstream patch or our implementation
return redis.NewStore(opts...)
case TypeRedisSentinel:
redisMaster := ""
redisNodes := []string{}
for _, node := range options.Nodes {
parts := strings.SplitN(node, "/", 2)
if len(parts) != 2 {
return nil
}
// the first node is used to retrieve the redis master
redisNodes = append(redisNodes, parts[0])
if redisMaster == "" {
redisMaster = parts[1]
}
}
return redis.NewStore(
store.Database(options.Database),
store.Table(options.Table),
store.Nodes(redisNodes...),
redis.WithRedisOptions(redisopts.UniversalOptions{
MasterName: redisMaster,
}),
)
case TypeOCMem:
if ocMemStore == nil {
var memStore store.Store
sizeNum, _ := options.Context.Value(sizeContextKey{}).(int)
if sizeNum <= 0 {
memStore = memory.NewMultiMemStore()
} else {
memStore = memory.NewMultiMemStore(
store.WithContext(
memory.NewContext(
context.Background(),
map[string]interface{}{
"maxCap": sizeNum,
},
)),
)
}
ocMemStore = &memStore
}
return *ocMemStore
case TypeNatsJS:
ttl, _ := options.Context.Value(ttlContextKey{}).(time.Duration)
// TODO nats needs a DefaultTTL option as it does not support per Write TTL ...
// FIXME nats has restrictions on the key, we cannot use slashes AFAICT
// host, port, clusterid
return natsjs.NewStore(
append(opts,
natsjs.NatsOptions(nats.Options{Name: "TODO"}),
natsjs.DefaultTTL(ttl))...,
) // TODO test with ocis nats
case TypeMemory, "mem", "": // allow existing short form and use as default
return store.NewMemoryStore(opts...)
default:
// try to log an error
if options.Logger == nil {
options.Logger = logger.DefaultLogger
}
options.Logger.Logf(logger.ErrorLevel, "unknown store type: '%s', falling back to memory", storeType)
return store.NewMemoryStore(opts...)
}
}