forked from TrueCloudLab/frostfs-s3-gw
[#269] Add frostfsid cache configuration
(cherry picked from commit fec3b3f31e
)
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
377fa127b5
commit
c6d0e5fc44
7 changed files with 147 additions and 0 deletions
41
api/cache/cache_test.go
vendored
41
api/cache/cache_test.go
vendored
|
@ -3,10 +3,13 @@ package cache
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zaptest/observer"
|
"go.uber.org/zap/zaptest/observer"
|
||||||
|
@ -194,6 +197,44 @@ func TestNotificationConfigurationCacheType(t *testing.T) {
|
||||||
assertInvalidCacheEntry(t, cache.GetNotificationConfiguration(key), observedLog)
|
assertInvalidCacheEntry(t, cache.GetNotificationConfiguration(key), observedLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFrostFSIDSubjectCacheType(t *testing.T) {
|
||||||
|
logger, observedLog := getObservedLogger()
|
||||||
|
cache := NewFrostfsIDCache(DefaultFrostfsIDConfig(logger))
|
||||||
|
|
||||||
|
key, err := util.Uint160DecodeStringLE("4ea976429703418ef00fc4912a409b6a0b973034")
|
||||||
|
require.NoError(t, err)
|
||||||
|
value := &client.SubjectExtended{}
|
||||||
|
|
||||||
|
err = cache.PutSubject(key, value)
|
||||||
|
require.NoError(t, err)
|
||||||
|
val := cache.GetSubject(key)
|
||||||
|
require.Equal(t, value, val)
|
||||||
|
require.Equal(t, 0, observedLog.Len())
|
||||||
|
|
||||||
|
err = cache.cache.Set(key, "tmp")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assertInvalidCacheEntry(t, cache.GetSubject(key), observedLog)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFrostFSIDUserKeyCacheType(t *testing.T) {
|
||||||
|
logger, observedLog := getObservedLogger()
|
||||||
|
cache := NewFrostfsIDCache(DefaultFrostfsIDConfig(logger))
|
||||||
|
|
||||||
|
ns, name := "ns", "name"
|
||||||
|
value, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = cache.PutUserKey(ns, name, value.PublicKey())
|
||||||
|
require.NoError(t, err)
|
||||||
|
val := cache.GetUserKey(ns, name)
|
||||||
|
require.Equal(t, value.PublicKey(), val)
|
||||||
|
require.Equal(t, 0, observedLog.Len())
|
||||||
|
|
||||||
|
err = cache.cache.Set(ns+"/"+name, "tmp")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assertInvalidCacheEntry(t, cache.GetUserKey(ns, name), observedLog)
|
||||||
|
}
|
||||||
|
|
||||||
func assertInvalidCacheEntry(t *testing.T, val interface{}, observedLog *observer.ObservedLogs) {
|
func assertInvalidCacheEntry(t *testing.T, val interface{}, observedLog *observer.ObservedLogs) {
|
||||||
require.Nil(t, val)
|
require.Nil(t, val)
|
||||||
require.Equal(t, 1, observedLog.Len())
|
require.Equal(t, 1, observedLog.Len())
|
||||||
|
|
84
api/cache/frostfsid.go
vendored
Normal file
84
api/cache/frostfsid.go
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
|
"github.com/bluele/gcache"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FrostfsIDCache provides lru cache for frostfsid contract.
|
||||||
|
type FrostfsIDCache struct {
|
||||||
|
cache gcache.Cache
|
||||||
|
logger *zap.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type FrostfsIDCacheKey struct {
|
||||||
|
Target engine.Target
|
||||||
|
Name chain.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultFrostfsIDCacheSize is a default maximum number of entries in cache.
|
||||||
|
DefaultFrostfsIDCacheSize = 1e4
|
||||||
|
// DefaultFrostfsIDCacheLifetime is a default lifetime of entries in cache.
|
||||||
|
DefaultFrostfsIDCacheLifetime = time.Minute
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultFrostfsIDConfig returns new default cache expiration values.
|
||||||
|
func DefaultFrostfsIDConfig(logger *zap.Logger) *Config {
|
||||||
|
return &Config{
|
||||||
|
Size: DefaultFrostfsIDCacheSize,
|
||||||
|
Lifetime: DefaultFrostfsIDCacheLifetime,
|
||||||
|
Logger: logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFrostfsIDCache creates an object of FrostfsIDCache.
|
||||||
|
func NewFrostfsIDCache(config *Config) *FrostfsIDCache {
|
||||||
|
gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).Build()
|
||||||
|
return &FrostfsIDCache{cache: gc, logger: config.Logger}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubject returns a cached client.SubjectExtended. Returns nil if value is missing.
|
||||||
|
func (c *FrostfsIDCache) GetSubject(key util.Uint160) *client.SubjectExtended {
|
||||||
|
return get[client.SubjectExtended](c, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutSubject puts a client.SubjectExtended to cache.
|
||||||
|
func (c *FrostfsIDCache) PutSubject(key util.Uint160, subject *client.SubjectExtended) error {
|
||||||
|
return c.cache.Set(key, subject)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUserKey returns a cached *keys.PublicKey. Returns nil if value is missing.
|
||||||
|
func (c *FrostfsIDCache) GetUserKey(ns, name string) *keys.PublicKey {
|
||||||
|
return get[keys.PublicKey](c, ns+"/"+name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutUserKey puts a client.SubjectExtended to cache.
|
||||||
|
func (c *FrostfsIDCache) PutUserKey(ns, name string, userKey *keys.PublicKey) error {
|
||||||
|
return c.cache.Set(ns+"/"+name, userKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func get[T any](c *FrostfsIDCache, key any) *T {
|
||||||
|
entry, err := c.cache.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, ok := entry.(*T)
|
||||||
|
if !ok {
|
||||||
|
c.logger.Warn(logs.InvalidCacheEntryType, zap.String("actual", fmt.Sprintf("%T", entry)),
|
||||||
|
zap.String("expected", fmt.Sprintf("%T", result)))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -950,6 +950,15 @@ func getMorphPolicyCacheConfig(v *viper.Viper, l *zap.Logger) *cache.Config {
|
||||||
return cacheCfg
|
return cacheCfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFrostfsIDCacheConfig(v *viper.Viper, l *zap.Logger) *cache.Config {
|
||||||
|
cacheCfg := cache.DefaultFrostfsIDConfig(l)
|
||||||
|
|
||||||
|
cacheCfg.Lifetime = fetchCacheLifetime(v, l, cfgFrostfsIDCacheLifetime, cacheCfg.Lifetime)
|
||||||
|
cacheCfg.Size = fetchCacheSize(v, l, cfgFrostfsIDCacheSize, cacheCfg.Size)
|
||||||
|
|
||||||
|
return cacheCfg
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) initHandler() {
|
func (a *App) initHandler() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,8 @@ const ( // Settings.
|
||||||
cfgAccessControlCacheSize = "cache.accesscontrol.size"
|
cfgAccessControlCacheSize = "cache.accesscontrol.size"
|
||||||
cfgMorphPolicyCacheLifetime = "cache.morph_policy.lifetime"
|
cfgMorphPolicyCacheLifetime = "cache.morph_policy.lifetime"
|
||||||
cfgMorphPolicyCacheSize = "cache.morph_policy.size"
|
cfgMorphPolicyCacheSize = "cache.morph_policy.size"
|
||||||
|
cfgFrostfsIDCacheLifetime = "cache.frostfsid.lifetime"
|
||||||
|
cfgFrostfsIDCacheSize = "cache.frostfsid.size"
|
||||||
|
|
||||||
cfgAccessBoxCacheRemovingCheckInterval = "cache.accessbox.removing_check_interval"
|
cfgAccessBoxCacheRemovingCheckInterval = "cache.accessbox.removing_check_interval"
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,9 @@ S3_GW_CACHE_ACCESSCONTROL_SIZE=100000
|
||||||
# Cache which stores list of policy chains
|
# Cache which stores list of policy chains
|
||||||
S3_GW_CACHE_MORPH_POLICY_LIFETIME=1m
|
S3_GW_CACHE_MORPH_POLICY_LIFETIME=1m
|
||||||
S3_GW_CACHE_MORPH_POLICY_SIZE=10000
|
S3_GW_CACHE_MORPH_POLICY_SIZE=10000
|
||||||
|
# Cache which stores frostfsid subject info
|
||||||
|
S3_GW_CACHE_FROSTFSID_LIFETIME=1m
|
||||||
|
S3_GW_CACHE_FROSTFSID_SIZE=10000
|
||||||
|
|
||||||
# NATS
|
# NATS
|
||||||
S3_GW_NATS_ENABLED=true
|
S3_GW_NATS_ENABLED=true
|
||||||
|
|
|
@ -129,6 +129,10 @@ cache:
|
||||||
morph_policy:
|
morph_policy:
|
||||||
lifetime: 1m
|
lifetime: 1m
|
||||||
size: 10000
|
size: 10000
|
||||||
|
# Cache which stores frostfsid subject info
|
||||||
|
frostfsid:
|
||||||
|
lifetime: 1m
|
||||||
|
size: 10000
|
||||||
|
|
||||||
nats:
|
nats:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -418,6 +418,9 @@ cache:
|
||||||
morph_policy:
|
morph_policy:
|
||||||
lifetime: 30s
|
lifetime: 30s
|
||||||
size: 10000
|
size: 10000
|
||||||
|
frostfsid:
|
||||||
|
lifetime: 1m
|
||||||
|
size: 10000
|
||||||
```
|
```
|
||||||
|
|
||||||
| Parameter | Type | Default value | Description |
|
| Parameter | Type | Default value | Description |
|
||||||
|
@ -431,6 +434,7 @@ cache:
|
||||||
| `accessbox` | [Accessbox cache config](#accessbox-subsection) | `lifetime: 10m`<br>`size: 100` | Cache which stores access box with tokens by its address. |
|
| `accessbox` | [Accessbox cache config](#accessbox-subsection) | `lifetime: 10m`<br>`size: 100` | Cache which stores access box with tokens by its address. |
|
||||||
| `accesscontrol` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 100000` | Cache which stores owner to cache operation mapping. |
|
| `accesscontrol` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 100000` | Cache which stores owner to cache operation mapping. |
|
||||||
| `morph_policy` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 10000` | Cache which stores list of policy chains. |
|
| `morph_policy` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 10000` | Cache which stores list of policy chains. |
|
||||||
|
| `frostfsid` | [Cache config](#cache-subsection) | `lifetime: 1m`<br>`size: 10000` | Cache which stores FrostfsID subject info. |
|
||||||
|
|
||||||
#### `cache` subsection
|
#### `cache` subsection
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue