Initial release
This commit is contained in:
parent
be71075e18
commit
9818566369
10 changed files with 634 additions and 0 deletions
94
src/cache.go
Normal file
94
src/cache.go
Normal 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
|
||||
}
|
||||
Reference in a new issue