Archived
1
0
Fork 0

Initial release

This commit is contained in:
Julien Riou 2019-03-08 18:14:22 +01:00
commit 9818566369
No known key found for this signature in database
GPG key ID: BA3E15176E45E85D
10 changed files with 634 additions and 0 deletions

94
src/cache.go Normal file
View file

@ -0,0 +1,94 @@
package main
import (
"sync"
"time"
)
// Cache defines an interface to implement caching structure
type Cache interface {
Startup()
Get(string) (interface{}, error)
Set(string, interface{}) error
}
// MemoryCache caches data in an in-memory key-value store with a ttl in seconds
type MemoryCache struct {
mutex sync.Mutex
enabled bool
datastore map[string]interface{}
expireStore map[string]time.Time
ttl float64
interval float64
}
// NewCache creates a Cache instance
func NewCache(config CacheConfig) (Cache, error) {
enabled := false
if config.TTL > 0 {
enabled = true
}
if config.Interval == 0 {
config.Interval = 0.25
}
return &MemoryCache{
ttl: config.TTL,
interval: config.Interval,
enabled: enabled,
}, nil
}
// Startup starts cache management threads
func (c *MemoryCache) Startup() {
Debug("starting memory cache")
c.datastore = make(map[string]interface{})
c.expireStore = make(map[string]time.Time)
go c.expireThread()
}
// expireThread flushes datastore every ttl seconds
func (c *MemoryCache) expireThread() {
Debug("starting cache expire thread")
if c.enabled {
for {
c.mutex.Lock()
for key := range c.expireStore {
if time.Since(c.expireStore[key]).Seconds() > c.ttl {
Debug("deleting key '%s' from cache", key)
delete(c.datastore, key)
delete(c.expireStore, key)
}
}
c.mutex.Unlock()
time.Sleep(time.Duration(c.interval*1000) * time.Millisecond)
}
}
Debug("ending cache expire thread")
}
// Get a value from cache datastore
func (c *MemoryCache) Get(key string) (interface{}, error) {
if !c.enabled {
return nil, nil
}
value, ok := c.datastore[key]
if ok {
Debug("value for key '%s' found in cache", key)
return value, nil
}
Debug("value for key '%s' not found in cache", key)
return nil, nil
}
// Set a value into cache datastore with a key
func (c *MemoryCache) Set(key string, value interface{}) error {
if !c.enabled {
return nil
}
Debug("setting value for key '%s' in cache", key)
c.mutex.Lock()
defer c.mutex.Unlock()
c.datastore[key] = value
c.expireStore[key] = time.Now()
return nil
}