Skip to content

Instantly share code, notes, and snippets.

@bmishra
Last active May 11, 2018 06:58
Show Gist options
  • Save bmishra/a0cb24c0f8f2b86ab17c2040b87de973 to your computer and use it in GitHub Desktop.
Save bmishra/a0cb24c0f8f2b86ab17c2040b87de973 to your computer and use it in GitHub Desktop.
Simple in-memory cache
package cache
import (
"errors"
"time"
)
type request struct {
cmd string
key string
val interface{}
ttl int64 // seconds
response chan<- result
}
type result struct {
value interface{}
err error
}
type cacheItem struct {
value interface{}
expiry int64
}
// Error variables
var (
ErrNoSuchKey = errors.New("No such cache item")
ErrItemExpired = errors.New("Expired cache item")
)
// commands
const (
cmdGet = "GET"
cmdSet = "SET"
cmdExpire = "EXPIRE"
)
// Cache simple in-memory cache
type Cache struct{ requests chan request }
// New init new Cache
func New() *Cache {
cache := &Cache{requests: make(chan request)}
go cache.server()
return cache
}
// Get fetch a value from cache, returns error if key is missing
func (c *Cache) Get(key string) (interface{}, error) {
response := make(chan result)
c.requests <- request{cmdGet, key, nil, 0, response}
res := <-response
return res.value, res.err
}
// Set sets a key value pair into the cache
func (c *Cache) Set(key string, val interface{}, ttl int64) (interface{}, error) {
response := make(chan result)
c.requests <- request{cmdSet, key, val, ttl, response}
res := <-response
return res.value, res.err
}
// Expire remove an item from cache
func (c *Cache) Expire(key string) {
response := make(chan result)
c.requests <- request{cmdExpire, key, nil, 0, response}
}
func (c *Cache) server() {
cache := make(map[string]interface{})
for req := range c.requests {
switch req.cmd {
case cmdSet:
item := cacheItem{
value: req.val,
}
if req.ttl > 0 {
item.expiry = time.Now().Unix() + req.ttl
}
cache[req.key] = item
req.response <- result{1, nil}
case cmdGet:
e := cache[req.key]
if e == nil {
req.response <- result{nil, ErrNoSuchKey}
} else if e.(cacheItem).expiry > 0 && time.Now().Unix() > e.(cacheItem).expiry {
req.response <- result{nil, ErrItemExpired}
c.Expire(req.key)
} else {
req.response <- result{e.(cacheItem).value, nil}
}
case cmdExpire:
e := cache[req.key]
if e != nil {
delete(cache, req.key)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment