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 }