github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/chat/unfurl/cache.go (about)

     1  package unfurl
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	lru "github.com/hashicorp/golang-lru"
     8  	"github.com/keybase/client/go/protocol/gregor1"
     9  	"github.com/keybase/clockwork"
    10  )
    11  
    12  const defaultCacheLifetime = 10 * time.Minute
    13  const defaultCacheSize = 1000
    14  
    15  type cacheItem struct {
    16  	data  interface{}
    17  	ctime gregor1.Time
    18  }
    19  
    20  type unfurlCache struct {
    21  	sync.Mutex
    22  	cache *lru.Cache
    23  	clock clockwork.Clock
    24  }
    25  
    26  func newUnfurlCache() *unfurlCache {
    27  	cache, err := lru.New(defaultCacheSize)
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  	return &unfurlCache{
    32  		cache: cache,
    33  		clock: clockwork.NewRealClock(),
    34  	}
    35  }
    36  
    37  func (c *unfurlCache) setClock(clock clockwork.Clock) {
    38  	c.clock = clock
    39  }
    40  
    41  // get determines if the item is in the cache and newer than 10
    42  // minutes. We don't want to cache this value indefinitely in case the page
    43  // content changes.
    44  func (c *unfurlCache) get(key string) (res cacheItem, ok bool) {
    45  	c.Lock()
    46  	defer c.Unlock()
    47  
    48  	item, ok := c.cache.Get(key)
    49  	if !ok {
    50  		return res, false
    51  	}
    52  	cacheItem, ok := item.(cacheItem)
    53  	if !ok {
    54  		return res, false
    55  	}
    56  	valid := c.clock.Now().Sub(cacheItem.ctime.Time()) <= defaultCacheLifetime
    57  	if !valid {
    58  		c.cache.Remove(key)
    59  	}
    60  	return cacheItem, valid
    61  }
    62  
    63  func (c *unfurlCache) put(key string, data interface{}) {
    64  	c.Lock()
    65  	defer c.Unlock()
    66  	c.cache.Add(key, cacheItem{
    67  		data:  data,
    68  		ctime: gregor1.ToTime(c.clock.Now()),
    69  	})
    70  }