Initial commit

This commit is contained in:
Tyler 2019-10-02 00:10:27 -04:00
commit a205315b2f
6 changed files with 211 additions and 0 deletions

26
README.md Normal file
View File

@ -0,0 +1,26 @@
CacheInterface
--------------
An experimental interface to use different caches interchangeably via URIs
Example Cache URIs:
```
redis://server:port?db=0&password=test
memcache://server1:11211,server2:11211
```
Code
####
The CacheInterface interface has all methods. All clients will implement this on a best-effort basis.
```go
type CacheInterface interface {
Has(key string) bool
Get(key string) ([]byte, error)
Set(key string, val interface{}, ttl time.Duration) (err error)
Del(key string) error
}
```
Note: Set will automatically attempt to store byte arrays and strings directly, and encode the rest with JSON.

48
cache.go Normal file
View File

@ -0,0 +1,48 @@
package cache
import (
"errors"
"net/url"
"strings"
"time"
)
const (
Memcache = "memcache"
Redis = "redis"
)
var (
ErrInvalidDriver = errors.New("invalid driver")
)
type CacheInterface interface {
Has(key string) bool
Get(key string) ([]byte, error)
Set(key string, val interface{}, ttl time.Duration) (err error)
Del(key string) error
}
func New(uri string) (CacheInterface, error) {
u, err := url.Parse(uri)
if err != nil {
return nil, err
}
query := u.Query()
switch u.Scheme {
case Redis:
return NewRedisCache(RedisSettings{
Address: u.Host,
Password: query.Get("password"),
})
case Memcache:
return NewMemcacheCache(MemcacheSettings{
Servers: strings.Split(u.Host, ","),
})
}
return nil, ErrInvalidDriver
}

63
cache_memcache.go Normal file
View File

@ -0,0 +1,63 @@
package cache
import (
"encoding/json"
"github.com/bradfitz/gomemcache/memcache"
"time"
)
type MemcacheSettings struct {
Servers []string
}
type MemcacheCache struct {
backend *memcache.Client
}
func NewMemcacheCache(s MemcacheSettings) (CacheInterface, error) {
c := memcache.New(s.Servers...)
return &MemcacheCache{
backend: c,
}, nil
}
func (mc *MemcacheCache) Has(key string) bool {
_, err := mc.backend.Get(key)
return err != nil
}
func (mc *MemcacheCache) Get(key string) ([]byte, error) {
item, err := mc.backend.Get(key)
if err != nil {
return nil, err
}
return item.Value, nil
}
func (mc *MemcacheCache) Set(key string, val interface{}, ttl time.Duration) error {
var v []byte
if b, ok := val.([]byte); ok {
v = b
} else if s, ok := val.(string); ok {
b = []byte(s)
} else {
b, err := json.Marshal(val)
if err != nil {
return err
}
v = b
}
return mc.backend.Set(&memcache.Item{Key: key, Value: v, Expiration: int32(ttl.Seconds())})
}
func (mc *MemcacheCache) Del(key string) error {
return mc.backend.Delete(key)
}

62
cache_redis.go Normal file
View File

@ -0,0 +1,62 @@
package cache
import (
"encoding/json"
"github.com/hoisie/redis"
"time"
)
type RedisSettings struct {
Address string
DB int
Password string
}
type RedisCache struct {
CacheInterface
c *redis.Client
}
func NewRedisCache(c RedisSettings) (CacheInterface, error) {
rc := &redis.Client{Addr: c.Address, Db: c.DB, Password: c.Password}
return &RedisCache{
c: rc,
}, nil
}
func (rc *RedisCache) Has(key string) bool {
b, _ := rc.c.Exists(key)
return b
}
func (rc *RedisCache) Get(key string) ([]byte, error) {
return rc.c.Get(key)
}
func (rc *RedisCache) Set(key string, val interface{}, ttl time.Duration) error {
var v []byte
if b, ok := val.([]byte); ok {
v = b
} else if s, ok := val.(string); ok {
b = []byte(s)
} else {
b, err := json.Marshal(val)
if err != nil {
return err
}
v = b
}
return rc.c.Setex(key, int64(ttl.Seconds()), v)
}
func (rc *RedisCache) Del(key string) error {
_, err := rc.c.Del(key)
return err
}

8
go.mod Normal file
View File

@ -0,0 +1,8 @@
module meow.tf/go/cacheinterface
go 1.12
require (
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0
)

4
go.sum Normal file
View File

@ -0,0 +1,4 @@
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0 h1:mjZV3MTu2A5gwfT5G9IIiLGdwZNciyVq5qqnmJJZ2JI=
github.com/hoisie/redis v0.0.0-20160730154456-b5c6e81454e0/go.mod h1:pMYMxVaKJqCDC1JUg/XbPJ4/fSazB25zORpFzqsIGIc=