git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/pool/cache.go (about) 1 package pool 2 3 import ( 4 "strings" 5 "sync/atomic" 6 7 "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" 8 lru "github.com/hashicorp/golang-lru/v2" 9 ) 10 11 type sessionCache struct { 12 cache *lru.Cache[string, *cacheValue] 13 currentEpoch atomic.Uint64 14 tokenDuration uint64 15 } 16 17 type cacheValue struct { 18 token session.Object 19 } 20 21 func newCache(tokenDuration uint64) (*sessionCache, error) { 22 cache, err := lru.New[string, *cacheValue](100) 23 if err != nil { 24 return nil, err 25 } 26 27 return &sessionCache{cache: cache, tokenDuration: tokenDuration}, nil 28 } 29 30 // Get returns a copy of the session token from the cache without signature 31 // and context related fields. Returns nil if token is missing in the cache. 32 // It is safe to modify and re-sign returned session token. 33 func (c *sessionCache) Get(key string) (session.Object, bool) { 34 value, ok := c.cache.Get(key) 35 if !ok { 36 return session.Object{}, false 37 } 38 39 if c.expired(value) { 40 c.cache.Remove(key) 41 return session.Object{}, false 42 } 43 44 return value.token, true 45 } 46 47 func (c *sessionCache) Put(key string, token session.Object) bool { 48 return c.cache.Add(key, &cacheValue{ 49 token: token, 50 }) 51 } 52 53 func (c *sessionCache) DeleteByPrefix(prefix string) { 54 for _, key := range c.cache.Keys() { 55 if strings.HasPrefix(key, prefix) { 56 c.cache.Remove(key) 57 } 58 } 59 } 60 61 func (c *sessionCache) updateEpoch(newEpoch uint64) { 62 epoch := c.currentEpoch.Load() 63 if newEpoch > epoch { 64 c.currentEpoch.Store(newEpoch) 65 } 66 } 67 68 func (c *sessionCache) expired(val *cacheValue) bool { 69 epoch := c.currentEpoch.Load() 70 preExpiredDur := c.tokenDuration / 2 71 if preExpiredDur == 0 { 72 preExpiredDur = 1 73 } 74 75 return val.token.ExpiredAt(epoch + preExpiredDur) 76 } 77 78 func (c *sessionCache) Epoch() uint64 { 79 return c.currentEpoch.Load() 80 }