94 lines
1.8 KiB
Go
94 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)
|
||
|
}
|