2023-10-16 06:27:21 +00:00
|
|
|
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 {
|
2024-02-16 15:24:27 +00:00
|
|
|
gc := gcache.New(config.Size).LRU().Expiration(config.Lifetime).EvictedFunc(func(_ interface{}, val interface{}) {
|
2023-10-16 06:27:21 +00:00
|
|
|
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)))
|
|
|
|
}
|
|
|
|
|
2024-01-22 09:33:59 +00:00
|
|
|
if !session.Acquired.Load() {
|
|
|
|
session.Cancel()
|
|
|
|
}
|
2023-10-16 06:27:21 +00:00
|
|
|
}).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 {
|
2024-01-22 09:33:59 +00:00
|
|
|
s := l.GetListSession(key)
|
|
|
|
if s != nil && s != session {
|
|
|
|
if !s.Acquired.Load() {
|
|
|
|
s.Cancel()
|
|
|
|
}
|
|
|
|
}
|
2023-10-16 06:27:21 +00:00
|
|
|
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
|
|
|
|
}
|