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  }