package cache import ( "time" lru "github.com/hashicorp/golang-lru" ) type Key interface { Key() interface{} } type Value interface { Stale() bool Value() interface{} } type item struct { key interface{} value interface{} expireOn time.Time } func NewItem(key, value interface{}, expires time.Duration) *item { return &item{ key: key, value: value, expireOn: time.Now().Add(expires), } } func (e *item) Stale() bool { if e == nil || e.value == nil { return true } return time.Now().After(e.expireOn) } func (s *item) Value() interface{} { return s.value } type Cacher interface { Add(Key, Value) Has(Key) bool Get(Key) (Value, bool) Remove(Key) } type arcCache struct { cache *lru.ARCCache } func NewARC(size int) (Cacher, error) { arc, err := lru.NewARC(size) if err != nil { return nil, err } return &arcCache{cache: arc}, nil } func (c *arcCache) Add(key Key, value Value) { c.cache.Add(key.Key(), value) } func (c *arcCache) Get(key Key) (Value, bool) { if v, ok := c.cache.Get(key.Key()); ok { if value, ok := v.(Value); ok && !value.Stale() { return value, true } c.cache.Remove(key.Key()) } return nil, false } func (c *arcCache) Has(key Key) bool { _, ok := c.Get(key) return ok } func (c *arcCache) Remove(key Key) { c.cache.Remove(key.Key()) }