2021-10-25 12:57:55 +00:00
|
|
|
package pool
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
2022-02-16 06:57:14 +00:00
|
|
|
"sync/atomic"
|
2021-10-25 12:57:55 +00:00
|
|
|
|
2023-03-07 11:20:03 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
2022-12-30 10:44:07 +00:00
|
|
|
lru "github.com/hashicorp/golang-lru/v2"
|
2021-10-25 12:57:55 +00:00
|
|
|
)
|
|
|
|
|
2022-03-11 11:57:35 +00:00
|
|
|
type sessionCache struct {
|
2022-12-30 10:44:07 +00:00
|
|
|
cache *lru.Cache[string, *cacheValue]
|
2023-05-19 11:58:30 +00:00
|
|
|
currentEpoch atomic.Uint64
|
2021-10-25 12:57:55 +00:00
|
|
|
}
|
|
|
|
|
2022-02-02 11:18:05 +00:00
|
|
|
type cacheValue struct {
|
2022-04-07 16:09:15 +00:00
|
|
|
token session.Object
|
2022-02-02 11:18:05 +00:00
|
|
|
}
|
|
|
|
|
2022-03-11 11:57:35 +00:00
|
|
|
func newCache() (*sessionCache, error) {
|
2022-12-30 10:44:07 +00:00
|
|
|
cache, err := lru.New[string, *cacheValue](100)
|
2021-11-08 13:28:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2021-10-25 12:57:55 +00:00
|
|
|
}
|
2021-11-08 13:28:28 +00:00
|
|
|
|
2022-03-11 11:57:35 +00:00
|
|
|
return &sessionCache{cache: cache}, nil
|
2021-10-25 12:57:55 +00:00
|
|
|
}
|
|
|
|
|
2022-04-06 08:05:08 +00:00
|
|
|
// Get returns a copy of the session token from the cache without signature
|
|
|
|
// and context related fields. Returns nil if token is missing in the cache.
|
|
|
|
// It is safe to modify and re-sign returned session token.
|
2022-04-07 16:09:15 +00:00
|
|
|
func (c *sessionCache) Get(key string) (session.Object, bool) {
|
2022-12-30 10:44:07 +00:00
|
|
|
value, ok := c.cache.Get(key)
|
2021-10-25 12:57:55 +00:00
|
|
|
if !ok {
|
2022-04-07 16:09:15 +00:00
|
|
|
return session.Object{}, false
|
2021-10-25 12:57:55 +00:00
|
|
|
}
|
2022-02-02 11:18:05 +00:00
|
|
|
|
2022-02-16 06:57:14 +00:00
|
|
|
if c.expired(value) {
|
|
|
|
c.cache.Remove(key)
|
2022-04-07 16:09:15 +00:00
|
|
|
return session.Object{}, false
|
2022-02-16 06:57:14 +00:00
|
|
|
}
|
|
|
|
|
2022-04-07 16:09:15 +00:00
|
|
|
return value.token, true
|
2022-02-02 11:18:05 +00:00
|
|
|
}
|
|
|
|
|
2022-04-07 16:09:15 +00:00
|
|
|
func (c *sessionCache) Put(key string, token session.Object) bool {
|
2022-02-02 11:18:05 +00:00
|
|
|
return c.cache.Add(key, &cacheValue{
|
|
|
|
token: token,
|
|
|
|
})
|
2021-10-25 12:57:55 +00:00
|
|
|
}
|
|
|
|
|
2022-03-11 11:57:35 +00:00
|
|
|
func (c *sessionCache) DeleteByPrefix(prefix string) {
|
2021-11-08 13:28:28 +00:00
|
|
|
for _, key := range c.cache.Keys() {
|
2022-12-30 10:44:07 +00:00
|
|
|
if strings.HasPrefix(key, prefix) {
|
2021-10-25 12:57:55 +00:00
|
|
|
c.cache.Remove(key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-02-16 06:57:14 +00:00
|
|
|
|
2022-04-05 09:15:13 +00:00
|
|
|
func (c *sessionCache) updateEpoch(newEpoch uint64) {
|
2023-05-19 11:58:30 +00:00
|
|
|
epoch := c.currentEpoch.Load()
|
2022-02-16 06:57:14 +00:00
|
|
|
if newEpoch > epoch {
|
2023-05-19 11:58:30 +00:00
|
|
|
c.currentEpoch.Store(newEpoch)
|
2022-02-16 06:57:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *sessionCache) expired(val *cacheValue) bool {
|
2023-05-19 11:58:30 +00:00
|
|
|
epoch := c.currentEpoch.Load()
|
2023-01-26 12:14:22 +00:00
|
|
|
// use epoch+1 (clear cache beforehand) to prevent 'expired session token' error right after epoch tick
|
|
|
|
return val.token.ExpiredAt(epoch + 1)
|
2022-02-16 06:57:14 +00:00
|
|
|
}
|