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 ( // ListMultipartSessionCache contains cache for list multiparts session (during pagination). ListMultipartSessionCache struct { cache gcache.Cache logger *zap.Logger } // ListMultipartSessionKey is a key to find a ListMultipartSessionCache's entry. ListMultipartSessionKey struct { cid cid.ID prefix string marker string uploadID string } ) const ( // DefaultListMultipartSessionCacheLifetime is a default lifetime of entries in cache of ListMultipartUploads. DefaultListMultipartSessionCacheLifetime = time.Minute // DefaultListMultipartSessionCacheSize is a default size of cache of ListMultipartUploads. DefaultListMultipartSessionCacheSize = 100 ) // DefaultListMultipartSessionConfig returns new default cache expiration values. func DefaultListMultipartSessionConfig(logger *zap.Logger) *Config { return &Config{ Size: DefaultListMultipartSessionCacheSize, Lifetime: DefaultListMultipartSessionCacheLifetime, Logger: logger, } } func (k *ListMultipartSessionKey) String() string { return k.cid.EncodeToString() + k.prefix + k.marker + k.uploadID } // NewListMultipartSessionCache is a constructor which creates an object of ListObjectsCache with the given lifetime of entries. func NewListMultipartSessionCache(config *Config) *ListMultipartSessionCache { gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).EvictedFunc(func(_ interface{}, val interface{}) { session, ok := val.(*data.ListMultipartSession) 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 &ListMultipartSessionCache{cache: gc, logger: config.Logger} } // GetListMultipartSession returns a session of ListMultipartUploads request. func (l *ListMultipartSessionCache) GetListMultipartSession(key ListMultipartSessionKey) *data.ListMultipartSession { entry, err := l.cache.Get(key) if err != nil { return nil } result, ok := entry.(*data.ListMultipartSession) 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 } // PutListMultipartSession puts a ListMultipartUploads session info to cache. func (l *ListMultipartSessionCache) PutListMultipartSession(key ListMultipartSessionKey, session *data.ListMultipartSession) error { s := l.GetListMultipartSession(key) if s != nil && s != session { if !s.Acquired.Load() { s.Cancel() } } return l.cache.Set(key, session) } // DeleteListMultipartSession removes key from cache. func (l *ListMultipartSessionCache) DeleteListMultipartSession(key ListMultipartSessionKey) { l.cache.Remove(key) } // CreateListMultipartSessionCacheKey returns ListMultipartSessionKey with the given CID, prefix, marker and uploadID. func CreateListMultipartSessionCacheKey(cnr cid.ID, prefix, marker, uploadID string) ListMultipartSessionKey { p := ListMultipartSessionKey{ cid: cnr, prefix: prefix, marker: marker, uploadID: uploadID, } return p }