package cache import ( "fmt" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" "github.com/bluele/gcache" "go.uber.org/zap" ) type ( // ListSessionCache contains cache for list session (during pagination). ListSessionCache struct { cache gcache.Cache logger *zap.Logger } // ListSessionKey is a key to find a ListSessionCache's entry. ListSessionKey struct { cid cid.ID prefix string token string } ) const ( // DefaultListSessionCacheLifetime is a default lifetime of entries in cache of ListObjects. DefaultListSessionCacheLifetime = time.Second * 60 // DefaultListSessionCacheSize is a default size of cache of ListObjects. DefaultListSessionCacheSize = 100 ) // DefaultListSessionConfig returns new default cache expiration values. func DefaultListSessionConfig(logger *zap.Logger) *Config { return &Config{ Size: DefaultListSessionCacheSize, Lifetime: DefaultListSessionCacheLifetime, Logger: logger, } } func (k *ListSessionKey) String() string { return k.cid.EncodeToString() + k.prefix + k.token } // NewListSessionCache is a constructor which creates an object of ListObjectsCache with the given lifetime of entries. func NewListSessionCache(config *Config) *ListSessionCache { gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).EvictedFunc(func(_ interface{}, val interface{}) { session, ok := val.(*data.ListSession) if !ok { config.Logger.Warn(logs.InvalidCacheEntryType, zap.String("actual", fmt.Sprintf("%T", val)), zap.String("expected", fmt.Sprintf("%T", session))) } if !session.Acquired.Load() { session.Cancel() } }).Build() return &ListSessionCache{cache: gc, logger: config.Logger} } // GetListSession returns a list of ObjectInfo. func (l *ListSessionCache) GetListSession(key ListSessionKey) *data.ListSession { entry, err := l.cache.Get(key) if err != nil { return nil } result, ok := entry.(*data.ListSession) if !ok { l.logger.Warn(logs.InvalidCacheEntryType, zap.String("actual", fmt.Sprintf("%T", entry)), zap.String("expected", fmt.Sprintf("%T", result))) return nil } return result } // PutListSession puts a list of object versions to cache. func (l *ListSessionCache) PutListSession(key ListSessionKey, session *data.ListSession) error { s := l.GetListSession(key) if s != nil && s != session { if !s.Acquired.Load() { s.Cancel() } } return l.cache.Set(key, session) } // DeleteListSession removes key from cache. func (l *ListSessionCache) DeleteListSession(key ListSessionKey) { l.cache.Remove(key) } // CreateListSessionCacheKey returns ListSessionKey with the given CID, prefix and token. func CreateListSessionCacheKey(cnr cid.ID, prefix, token string) ListSessionKey { p := ListSessionKey{ cid: cnr, prefix: prefix, token: token, } return p }