cache/cache.go
2021-11-19 13:22:01 +01:00

93 lines
1.8 KiB
Go

// Package cache defines an in-memory key-value store.
//
// It supports exîration dates andcan store arbitrary values of any type.
// Keys must be strings.
package cache
import (
"sync"
"time"
)
type entry struct {
expirationDate time.Time
value interface{}
}
// Cache is an in-memory key-value store.
type Cache struct {
data map[string]entry
mu *sync.RWMutex
}
// New instantiate a new cache.
func New() *Cache {
return &Cache{
data: make(map[string]entry),
mu: &sync.RWMutex{},
}
}
// Put stores a value in the cache under the given key.
func (c *Cache) Put(key string, val interface{}) {
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = entry{time.Time{}, val}
}
// PutTTL stores a value in the cache under the given key. The value will
// be expired after the given ttl.
//
// A 0 ttl value disables the expiration of the value.
func (c *Cache) PutTTL(key string, val interface{}, ttl time.Duration) {
var exp time.Time
if ttl == 0 {
exp = time.Time{}
} else {
exp = time.Now().Add(ttl)
}
c.mu.Lock()
defer c.mu.Unlock()
c.data[key] = entry{exp, val}
}
// Get returns the value asspciated with the given key.
// The second return values indicates if the cache hs been hit or not.
func (c Cache) Get(key string) (interface{}, bool) {
c.mu.RLock()
v, ok := c.data[key]
c.mu.RUnlock()
if !ok {
return nil, false
}
if !v.expirationDate.IsZero() && v.expirationDate.Before(time.Now()) {
c.Del(key)
return nil, false
}
return v.value, ok
}
// Del deletes the entry for the givzn key.
// It does not fail if the key does not exist.
func (c *Cache) Del(key string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.data, key)
}
// Count returns the total number of entries in the cache (vamid and expired).
func (c Cache) Count() int {
c.mu.RLock()
defer c.mu.RUnlock()
return len(c.data)
}