2019-10-03 00:17:34 +00:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"github.com/patrickmn/go-cache"
|
2019-10-05 20:15:19 +00:00
|
|
|
"github.com/vmihailenco/msgpack/v4"
|
2019-10-03 00:17:34 +00:00
|
|
|
"reflect"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2019-10-05 20:42:59 +00:00
|
|
|
ErrMemoryCacheNotExists = errors.New("item does not exist")
|
2019-10-03 00:17:34 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type MemoryCache struct {
|
|
|
|
c *cache.Cache
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewMemoryCache(cleanupTime time.Duration) (CacheInterface, error) {
|
|
|
|
c := cache.New(1*time.Minute, cleanupTime)
|
|
|
|
|
|
|
|
return &MemoryCache{c: c}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mc *MemoryCache) Has(key string) bool {
|
|
|
|
_, exists := mc.c.Get(key)
|
|
|
|
|
|
|
|
return exists
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mc *MemoryCache) Get(key string, dst ...interface{}) ([]byte, error) {
|
|
|
|
item, exists := mc.c.Get(key)
|
|
|
|
|
|
|
|
if !exists {
|
2019-10-03 00:38:20 +00:00
|
|
|
return nil, ErrMemoryCacheNotExists
|
|
|
|
}
|
|
|
|
|
2019-10-05 20:56:24 +00:00
|
|
|
return memoryCacheGet(item, dst...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mc *MemoryCache) Set(key string, val interface{}, ttl time.Duration) error {
|
|
|
|
mc.c.Set(key, val, ttl)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mc *MemoryCache) Del(key string) error {
|
|
|
|
mc.c.Delete(key)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func memoryCacheGet(item interface{}, dst ...interface{}) ([]byte, error) {
|
2019-10-03 00:38:20 +00:00
|
|
|
if len(dst) == 0 {
|
2019-10-05 20:15:19 +00:00
|
|
|
switch item.(type) {
|
|
|
|
case string:
|
|
|
|
return []byte(item.(string)), nil
|
|
|
|
case []byte:
|
|
|
|
return item.([]byte), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return msgpack.Marshal(item)
|
2019-10-03 00:17:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
v := dst[0]
|
|
|
|
|
|
|
|
switch v := v.(type) {
|
|
|
|
case *string:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(string)
|
2019-10-05 20:42:59 +00:00
|
|
|
return []byte(item.(string)), nil
|
2019-10-03 00:17:34 +00:00
|
|
|
}
|
|
|
|
case *[]byte:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.([]byte)
|
2019-10-05 20:42:59 +00:00
|
|
|
return item.([]byte), nil
|
2019-10-03 00:17:34 +00:00
|
|
|
}
|
|
|
|
case *int:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(int)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *int8:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(int8)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *int16:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(int16)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *int32:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(int32)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *int64:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(int64)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *uint:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(uint)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *uint8:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(uint8)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *uint16:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(uint16)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *uint32:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(uint32)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *uint64:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(uint64)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *bool:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(bool)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *float32:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(float32)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *float64:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(float64)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *[]string:
|
|
|
|
*v = item.([]string)
|
|
|
|
return nil, nil
|
|
|
|
case *map[string]string:
|
|
|
|
*v = item.(map[string]string)
|
|
|
|
return nil, nil
|
|
|
|
case *map[string]interface{}:
|
|
|
|
*v = item.(map[string]interface{})
|
|
|
|
return nil, nil
|
|
|
|
case *time.Duration:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(time.Duration)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
case *time.Time:
|
|
|
|
if v != nil {
|
|
|
|
*v = item.(time.Time)
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vv := reflect.ValueOf(dst[0])
|
|
|
|
|
|
|
|
if !vv.IsValid() {
|
|
|
|
return nil, errors.New("dst pointer is not valid")
|
|
|
|
}
|
|
|
|
|
|
|
|
if vv.Kind() != reflect.Ptr {
|
|
|
|
return nil, errors.New("dst pointer is not a pointer")
|
|
|
|
}
|
|
|
|
|
|
|
|
vv = vv.Elem()
|
|
|
|
|
|
|
|
if !vv.IsValid() {
|
|
|
|
return nil, errors.New("dst pointer is not a valid element")
|
|
|
|
}
|
|
|
|
|
|
|
|
vv.Set(reflect.ValueOf(item))
|
|
|
|
|
|
|
|
return nil, nil
|
|
|
|
}
|