1
0
Fork 0
mirror of https://github.com/alice-lg/birdwatcher.git synced 2025-03-09 00:00:05 +01:00
birdwatcher/bird/memory_cache.go
Benedikt Rudolph e6ed0cb901 Refactor housekeeping and memory cache
* run Expire() only on MemoryCaches
* make initialization of the cache look pretty
2019-02-20 11:17:13 +01:00

81 lines
1.6 KiB
Go

package bird
import (
"errors"
"sync"
"time"
)
// Implementation of the MemoryCache backend.
type MemoryCache struct {
sync.RWMutex
m map[string]Parsed
}
func NewMemoryCache() (*MemoryCache, error) {
var cache *MemoryCache
cache = &MemoryCache{m: make(map[string]Parsed)}
return cache, nil
}
func (c *MemoryCache) Get(key string) (Parsed, error) {
c.RLock()
val, ok := c.m[key]
c.RUnlock()
if !ok { // cache miss
return NilParse, errors.New("Failed to retrive key '" + key + "' from MemoryCache.")
}
ttl, correct := val["ttl"].(time.Time)
if !correct {
return NilParse, errors.New("Invalid TTL value for key '" + key + "'")
}
if ttl.Before(time.Now()) {
return val, errors.New("TTL expired for key '" + key + "'") // TTL expired
} else {
return val, nil // cache hit
}
}
func (c *MemoryCache) Set(key string, val Parsed, ttl int) error {
switch {
case ttl == 0:
return nil // do not cache
case ttl > 0:
cachedAt := time.Now().UTC()
cacheTtl := cachedAt.Add(time.Duration(ttl) * time.Minute)
c.Lock()
// This is not a really ... clean way of doing this.
val["ttl"] = cacheTtl
val["cached_at"] = cachedAt
c.m[key] = val
c.Unlock()
return nil
default: // ttl negative - invalid
return errors.New("Negative TTL value for key" + key)
}
}
func (c *MemoryCache) Expire() int {
c.Lock()
expiredKeys := []string{}
for key, _ := range c.m {
ttl, correct := c.m[key]["ttl"].(time.Time)
if !correct || ttl.Before(time.Now()) {
expiredKeys = append(expiredKeys, key)
}
}
for _, key := range expiredKeys {
delete(c.m, key)
}
c.Unlock()
return len(expiredKeys)
}