forked from TrueCloudLab/frostfs-s3-gw
105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
|
package cache
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||
|
)
|
||
|
|
||
|
/*
|
||
|
This is an implementation of a cache for ListObjectsV2/V1 which we can return to users when we receive a ListObjects
|
||
|
request.
|
||
|
|
||
|
The cache is a map which has a key: ObjectsListKey struct and a value: list of objects. After putting a record we
|
||
|
start a timer (via time.AfterFunc) that removes the record after DefaultObjectsListCacheLifetime value.
|
||
|
|
||
|
When we get a request from the user we just try to find the suitable and non-expired cache and then we return
|
||
|
the list of objects. Otherwise we send the request to NeoFS.
|
||
|
*/
|
||
|
|
||
|
// ObjectsListCache provides interface for cache of ListObjectsV2 in a layer struct.
|
||
|
type (
|
||
|
ObjectsListCache interface {
|
||
|
Get(key ObjectsListKey) []*api.ObjectInfo
|
||
|
Put(key ObjectsListKey, objects []*api.ObjectInfo)
|
||
|
}
|
||
|
)
|
||
|
|
||
|
// DefaultObjectsListCacheLifetime is a default lifetime of entries in cache of ListObjects.
|
||
|
const DefaultObjectsListCacheLifetime = time.Second * 60
|
||
|
|
||
|
const (
|
||
|
// ListObjectsMethod is used to mark a cache entry for ListObjectsV1/V2.
|
||
|
ListObjectsMethod = "listObjects"
|
||
|
// ListVersionsMethod is used to mark a cache entry for ListObjectVersions.
|
||
|
ListVersionsMethod = "listVersions"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
// ListObjectsCache contains cache for ListObjects and ListObjectVersions.
|
||
|
ListObjectsCache struct {
|
||
|
cacheLifetime time.Duration
|
||
|
caches map[ObjectsListKey]objectsListEntry
|
||
|
mtx sync.RWMutex
|
||
|
}
|
||
|
objectsListEntry struct {
|
||
|
list []*api.ObjectInfo
|
||
|
}
|
||
|
// ObjectsListKey is a key to find a ObjectsListCache's entry.
|
||
|
ObjectsListKey struct {
|
||
|
Method string
|
||
|
Key string
|
||
|
Delimiter string
|
||
|
Prefix string
|
||
|
}
|
||
|
)
|
||
|
|
||
|
// NewObjectsListCache is a constructor which creates an object of ListObjectsCache with given lifetime of entries.
|
||
|
func NewObjectsListCache(lifetime time.Duration) *ListObjectsCache {
|
||
|
return &ListObjectsCache{
|
||
|
caches: make(map[ObjectsListKey]objectsListEntry),
|
||
|
cacheLifetime: lifetime,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get return list of ObjectInfo.
|
||
|
func (l *ListObjectsCache) Get(key ObjectsListKey) []*api.ObjectInfo {
|
||
|
l.mtx.RLock()
|
||
|
defer l.mtx.RUnlock()
|
||
|
if val, ok := l.caches[key]; ok {
|
||
|
return val.list
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// Put put a list of objects to cache.
|
||
|
func (l *ListObjectsCache) Put(key ObjectsListKey, objects []*api.ObjectInfo) {
|
||
|
if len(objects) == 0 {
|
||
|
return
|
||
|
}
|
||
|
var c objectsListEntry
|
||
|
l.mtx.Lock()
|
||
|
defer l.mtx.Unlock()
|
||
|
c.list = objects
|
||
|
l.caches[key] = c
|
||
|
time.AfterFunc(l.cacheLifetime, func() {
|
||
|
l.mtx.Lock()
|
||
|
delete(l.caches, key)
|
||
|
l.mtx.Unlock()
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// CreateObjectsListCacheKey returns ObjectsListKey with given CID, method, prefix, and delimiter.
|
||
|
func CreateObjectsListCacheKey(cid *cid.ID, method, prefix, delimiter string) (ObjectsListKey, error) {
|
||
|
p := ObjectsListKey{
|
||
|
Method: method,
|
||
|
Key: cid.String(),
|
||
|
Delimiter: delimiter,
|
||
|
Prefix: prefix,
|
||
|
}
|
||
|
|
||
|
return p, nil
|
||
|
}
|