replace zxq.co/ripple/hanayo
This commit is contained in:
181
vendor/github.com/gin-gonic/contrib/cache/redis.go
generated
vendored
Normal file
181
vendor/github.com/gin-gonic/contrib/cache/redis.go
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Wraps the Redis client to meet the Cache interface.
|
||||
type RedisStore struct {
|
||||
pool *redis.Pool
|
||||
defaultExpiration time.Duration
|
||||
}
|
||||
|
||||
// until redigo supports sharding/clustering, only one host will be in hostList
|
||||
func NewRedisCache(host string, password string, defaultExpiration time.Duration) *RedisStore {
|
||||
var pool = &redis.Pool{
|
||||
MaxIdle: 5,
|
||||
IdleTimeout: 240 * time.Second,
|
||||
Dial: func() (redis.Conn, error) {
|
||||
// the redis protocol should probably be made sett-able
|
||||
c, err := redis.Dial("tcp", host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(password) > 0 {
|
||||
if _, err := c.Do("AUTH", password); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// check with PING
|
||||
if _, err := c.Do("PING"); err != nil {
|
||||
c.Close()
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return c, err
|
||||
},
|
||||
// custom connection test method
|
||||
TestOnBorrow: func(c redis.Conn, t time.Time) error {
|
||||
if _, err := c.Do("PING"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return &RedisStore{pool, defaultExpiration}
|
||||
}
|
||||
|
||||
func (c *RedisStore) Set(key string, value interface{}, expires time.Duration) error {
|
||||
return c.invoke(c.pool.Get().Do, key, value, expires)
|
||||
}
|
||||
|
||||
func (c *RedisStore) Add(key string, value interface{}, expires time.Duration) error {
|
||||
conn := c.pool.Get()
|
||||
if exists(conn, key) {
|
||||
return ErrNotStored
|
||||
}
|
||||
return c.invoke(conn.Do, key, value, expires)
|
||||
}
|
||||
|
||||
func (c *RedisStore) Replace(key string, value interface{}, expires time.Duration) error {
|
||||
conn := c.pool.Get()
|
||||
if !exists(conn, key) {
|
||||
return ErrNotStored
|
||||
}
|
||||
err := c.invoke(conn.Do, key, value, expires)
|
||||
if value == nil {
|
||||
return ErrNotStored
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RedisStore) Get(key string, ptrValue interface{}) error {
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
raw, err := conn.Do("GET", key)
|
||||
if raw == nil {
|
||||
return ErrCacheMiss
|
||||
}
|
||||
item, err := redis.Bytes(raw, err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return deserialize(item, ptrValue)
|
||||
}
|
||||
|
||||
func exists(conn redis.Conn, key string) bool {
|
||||
retval, _ := redis.Bool(conn.Do("EXISTS", key))
|
||||
return retval
|
||||
}
|
||||
|
||||
func (c *RedisStore) Delete(key string) error {
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
if !exists(conn, key) {
|
||||
return ErrCacheMiss
|
||||
}
|
||||
_, err := conn.Do("DEL", key)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *RedisStore) Increment(key string, delta uint64) (uint64, error) {
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
// Check for existance *before* increment as per the cache contract.
|
||||
// redis will auto create the key, and we don't want that. Since we need to do increment
|
||||
// ourselves instead of natively via INCRBY (redis doesn't support wrapping), we get the value
|
||||
// and do the exists check this way to minimize calls to Redis
|
||||
val, err := conn.Do("GET", key)
|
||||
if val == nil {
|
||||
return 0, ErrCacheMiss
|
||||
}
|
||||
if err == nil {
|
||||
currentVal, err := redis.Int64(val, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var sum int64 = currentVal + int64(delta)
|
||||
_, err = conn.Do("SET", key, sum)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint64(sum), nil
|
||||
} else {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RedisStore) Decrement(key string, delta uint64) (newValue uint64, err error) {
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
// Check for existance *before* increment as per the cache contract.
|
||||
// redis will auto create the key, and we don't want that, hence the exists call
|
||||
if !exists(conn, key) {
|
||||
return 0, ErrCacheMiss
|
||||
}
|
||||
// Decrement contract says you can only go to 0
|
||||
// so we go fetch the value and if the delta is greater than the amount,
|
||||
// 0 out the value
|
||||
currentVal, err := redis.Int64(conn.Do("GET", key))
|
||||
if err == nil && delta > uint64(currentVal) {
|
||||
tempint, err := redis.Int64(conn.Do("DECRBY", key, currentVal))
|
||||
return uint64(tempint), err
|
||||
}
|
||||
tempint, err := redis.Int64(conn.Do("DECRBY", key, delta))
|
||||
return uint64(tempint), err
|
||||
}
|
||||
|
||||
func (c *RedisStore) Flush() error {
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
_, err := conn.Do("FLUSHALL")
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *RedisStore) invoke(f func(string, ...interface{}) (interface{}, error),
|
||||
key string, value interface{}, expires time.Duration) error {
|
||||
|
||||
switch expires {
|
||||
case DEFAULT:
|
||||
expires = c.defaultExpiration
|
||||
case FOREVER:
|
||||
expires = time.Duration(0)
|
||||
}
|
||||
|
||||
b, err := serialize(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conn := c.pool.Get()
|
||||
defer conn.Close()
|
||||
if expires > 0 {
|
||||
_, err := f("SETEX", key, int32(expires/time.Second), b)
|
||||
return err
|
||||
} else {
|
||||
_, err := f("SET", key, b)
|
||||
return err
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user