131 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package cache
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"github.com/vmihailenco/msgpack/v4"
 | |
| 	"net"
 | |
| 	"net/url"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	Memcache = "memcache"
 | |
| 	Redis    = "redis"
 | |
| 	Memory   = "memory"
 | |
| 	Lru      = "lru"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	ErrInvalidDriver = errors.New("invalid driver")
 | |
| )
 | |
| 
 | |
| type CacheInterface interface {
 | |
| 	Has(key string) bool
 | |
| 	Get(key string, dst ...interface{}) ([]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:
 | |
| 		port := u.Port()
 | |
| 
 | |
| 		if port == "" {
 | |
| 			port = "6379"
 | |
| 		}
 | |
| 
 | |
| 		return NewRedisCache(RedisSettings{
 | |
| 			Address:  net.JoinHostPort(u.Hostname(), port),
 | |
| 			Password: query.Get("password"),
 | |
| 		})
 | |
| 	case Memcache:
 | |
| 		return NewMemcacheCache(MemcacheSettings{
 | |
| 			Servers: strings.Split(u.Host, ","),
 | |
| 		})
 | |
| 	case Memory:
 | |
| 		cleanupTime := query.Get("cleanupTime")
 | |
| 
 | |
| 		if cleanupTime == "" {
 | |
| 			cleanupTime = "30"
 | |
| 		}
 | |
| 
 | |
| 		i, err := strconv.Atoi(cleanupTime)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		return NewMemoryCache(time.Duration(i) * time.Second)
 | |
| 	case Lru:
 | |
| 		size := query.Get("size")
 | |
| 
 | |
| 		if size == "" {
 | |
| 			size = "128"
 | |
| 		}
 | |
| 
 | |
| 		i, err := strconv.Atoi(size)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		return NewLruCache(i)
 | |
| 	}
 | |
| 
 | |
| 	return nil, ErrInvalidDriver
 | |
| }
 | |
| 
 | |
| func encodeValue(val interface{}) ([]byte, 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 := msgpack.Marshal(val)
 | |
| 
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		v = b
 | |
| 	}
 | |
| 
 | |
| 	return v, nil
 | |
| }
 | |
| 
 | |
| func decodeDst(b []byte, v interface{}) ([]byte, error) {
 | |
| 	switch v := v.(type) {
 | |
| 	case *[]byte:
 | |
| 		if v != nil {
 | |
| 			*v = b
 | |
| 			return b, nil
 | |
| 		}
 | |
| 	case *string:
 | |
| 		if v != nil {
 | |
| 			*v = string(b)
 | |
| 			return b, nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	err := msgpack.Unmarshal(b, v)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return b, nil
 | |
| }
 |