Merge pull request #674 from reterVision/master
Make redis cache timeout not trivial.
Showing
3 changed files
with
118 additions
and
14 deletions
| ... | @@ -35,11 +35,11 @@ type Cache interface { | ... | @@ -35,11 +35,11 @@ type Cache interface { |
| 35 | Incr(key string) error | 35 | Incr(key string) error |
| 36 | // decrease cached int value by key, as a counter. | 36 | // decrease cached int value by key, as a counter. |
| 37 | Decr(key string) error | 37 | Decr(key string) error |
| 38 | // check cached value is existed or not. | 38 | // check if cached value exists or not. |
| 39 | IsExist(key string) bool | 39 | IsExist(key string) bool |
| 40 | // clear all cache. | 40 | // clear all cache. |
| 41 | ClearAll() error | 41 | ClearAll() error |
| 42 | // start gc routine via config string setting. | 42 | // start gc routine based on config string settings. |
| 43 | StartAndGC(config string) error | 43 | StartAndGC(config string) error |
| 44 | } | 44 | } |
| 45 | 45 | ||
| ... | @@ -58,13 +58,13 @@ func Register(name string, adapter Cache) { | ... | @@ -58,13 +58,13 @@ func Register(name string, adapter Cache) { |
| 58 | adapters[name] = adapter | 58 | adapters[name] = adapter |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | // Create a new cache driver by adapter and config string. | 61 | // Create a new cache driver by adapter name and config string. |
| 62 | // config need to be correct JSON as string: {"interval":360}. | 62 | // config need to be correct JSON as string: {"interval":360}. |
| 63 | // it will start gc automatically. | 63 | // it will start gc automatically. |
| 64 | func NewCache(adapterName, config string) (Cache, error) { | 64 | func NewCache(adapterName, config string) (Cache, error) { |
| 65 | adapter, ok := adapters[adapterName] | 65 | adapter, ok := adapters[adapterName] |
| 66 | if !ok { | 66 | if !ok { |
| 67 | return nil, fmt.Errorf("cache: unknown adaptername %q (forgotten import?)", adapterName) | 67 | return nil, fmt.Errorf("cache: unknown adapter name %q (forgot to import?)", adapterName) |
| 68 | } | 68 | } |
| 69 | err := adapter.StartAndGC(config) | 69 | err := adapter.StartAndGC(config) |
| 70 | if err != nil { | 70 | if err != nil { | ... | ... |
| ... | @@ -47,7 +47,7 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa | ... | @@ -47,7 +47,7 @@ func (rc *RedisCache) do(commandName string, args ...interface{}) (reply interfa |
| 47 | 47 | ||
| 48 | // Get cache from redis. | 48 | // Get cache from redis. |
| 49 | func (rc *RedisCache) Get(key string) interface{} { | 49 | func (rc *RedisCache) Get(key string) interface{} { |
| 50 | v, err := rc.do("HGET", rc.key, key) | 50 | v, err := rc.do("GET", key) |
| 51 | if err != nil { | 51 | if err != nil { |
| 52 | return nil | 52 | return nil |
| 53 | } | 53 | } |
| ... | @@ -56,43 +56,66 @@ func (rc *RedisCache) Get(key string) interface{} { | ... | @@ -56,43 +56,66 @@ func (rc *RedisCache) Get(key string) interface{} { |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | // put cache to redis. | 58 | // put cache to redis. |
| 59 | // timeout is ignored. | ||
| 60 | func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { | 59 | func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { |
| 61 | _, err := rc.do("HSET", rc.key, key, val) | 60 | _, err := rc.do("SET", key, val) |
| 61 | if err != nil { | ||
| 62 | return nil | ||
| 63 | } | ||
| 64 | _, err = rc.do("HSET", rc.key, key, true) | ||
| 65 | if err != nil { | ||
| 66 | return nil | ||
| 67 | } | ||
| 68 | _, err = rc.do("EXPIRE", key, timeout) | ||
| 62 | return err | 69 | return err |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 65 | // delete cache in redis. | 72 | // delete cache in redis. |
| 66 | func (rc *RedisCache) Delete(key string) error { | 73 | func (rc *RedisCache) Delete(key string) error { |
| 67 | _, err := rc.do("HDEL", rc.key, key) | 74 | _, err := rc.do("DEL", key) |
| 75 | if err != nil { | ||
| 76 | return nil | ||
| 77 | } | ||
| 78 | _, err = rc.do("HDEL", rc.key, key) | ||
| 68 | return err | 79 | return err |
| 69 | } | 80 | } |
| 70 | 81 | ||
| 71 | // check cache exist in redis. | 82 | // check cache's existence in redis. |
| 72 | func (rc *RedisCache) IsExist(key string) bool { | 83 | func (rc *RedisCache) IsExist(key string) bool { |
| 73 | v, err := redis.Bool(rc.do("HEXISTS", rc.key, key)) | 84 | v, err := redis.Bool(rc.do("EXISTS", key)) |
| 74 | if err != nil { | 85 | if err != nil { |
| 75 | return false | 86 | return false |
| 76 | } | 87 | } |
| 77 | 88 | if v == false { | |
| 89 | _, err := rc.do("HDEL", rc.key, key) | ||
| 90 | if err != nil { | ||
| 91 | return false | ||
| 92 | } | ||
| 93 | } | ||
| 78 | return v | 94 | return v |
| 79 | } | 95 | } |
| 80 | 96 | ||
| 81 | // increase counter in redis. | 97 | // increase counter in redis. |
| 82 | func (rc *RedisCache) Incr(key string) error { | 98 | func (rc *RedisCache) Incr(key string) error { |
| 83 | _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, 1)) | 99 | _, err := redis.Bool(rc.do("INCRBY", key, 1)) |
| 84 | return err | 100 | return err |
| 85 | } | 101 | } |
| 86 | 102 | ||
| 87 | // decrease counter in redis. | 103 | // decrease counter in redis. |
| 88 | func (rc *RedisCache) Decr(key string) error { | 104 | func (rc *RedisCache) Decr(key string) error { |
| 89 | _, err := redis.Bool(rc.do("HINCRBY", rc.key, key, -1)) | 105 | _, err := redis.Bool(rc.do("INCRBY", key, -1)) |
| 90 | return err | 106 | return err |
| 91 | } | 107 | } |
| 92 | 108 | ||
| 93 | // clean all cache in redis. delete this redis collection. | 109 | // clean all cache in redis. delete this redis collection. |
| 94 | func (rc *RedisCache) ClearAll() error { | 110 | func (rc *RedisCache) ClearAll() error { |
| 95 | _, err := rc.do("DEL", rc.key) | 111 | cachedKeys, err := redis.Strings(rc.do("HKEYS", rc.key)) |
| 112 | for _, str := range cachedKeys { | ||
| 113 | _, err := rc.do("DEL", str) | ||
| 114 | if err != nil { | ||
| 115 | return nil | ||
| 116 | } | ||
| 117 | } | ||
| 118 | _, err = rc.do("DEL", rc.key) | ||
| 96 | return err | 119 | return err |
| 97 | } | 120 | } |
| 98 | 121 | ... | ... |
cache/redis/redis_test.go
0 → 100644
| 1 | // Beego (http://beego.me/) | ||
| 2 | |||
| 3 | // @description beego is an open-source, high-performance web framework for the Go programming language. | ||
| 4 | |||
| 5 | // @link http://github.com/astaxie/beego for the canonical source repository | ||
| 6 | |||
| 7 | // @license http://github.com/astaxie/beego/blob/master/LICENSE | ||
| 8 | |||
| 9 | // @authors astaxie | ||
| 10 | |||
| 11 | package cache | ||
| 12 | |||
| 13 | import ( | ||
| 14 | "testing" | ||
| 15 | "time" | ||
| 16 | |||
| 17 | "github.com/beego/redigo/redis" | ||
| 18 | |||
| 19 | "github.com/astaxie/beego/cache" | ||
| 20 | ) | ||
| 21 | |||
| 22 | func TestRedisCache(t *testing.T) { | ||
| 23 | bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`) | ||
| 24 | if err != nil { | ||
| 25 | t.Error("init err") | ||
| 26 | } | ||
| 27 | if err = bm.Put("astaxie", 1, 10); err != nil { | ||
| 28 | t.Error("set Error", err) | ||
| 29 | } | ||
| 30 | if !bm.IsExist("astaxie") { | ||
| 31 | t.Error("check err") | ||
| 32 | } | ||
| 33 | |||
| 34 | time.Sleep(10 * time.Second) | ||
| 35 | |||
| 36 | if bm.IsExist("astaxie") { | ||
| 37 | t.Error("check err") | ||
| 38 | } | ||
| 39 | if err = bm.Put("astaxie", 1, 10); err != nil { | ||
| 40 | t.Error("set Error", err) | ||
| 41 | } | ||
| 42 | |||
| 43 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { | ||
| 44 | t.Error("get err") | ||
| 45 | } | ||
| 46 | |||
| 47 | if err = bm.Incr("astaxie"); err != nil { | ||
| 48 | t.Error("Incr Error", err) | ||
| 49 | } | ||
| 50 | |||
| 51 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 { | ||
| 52 | t.Error("get err") | ||
| 53 | } | ||
| 54 | |||
| 55 | if err = bm.Decr("astaxie"); err != nil { | ||
| 56 | t.Error("Decr Error", err) | ||
| 57 | } | ||
| 58 | |||
| 59 | if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { | ||
| 60 | t.Error("get err") | ||
| 61 | } | ||
| 62 | bm.Delete("astaxie") | ||
| 63 | if bm.IsExist("astaxie") { | ||
| 64 | t.Error("delete err") | ||
| 65 | } | ||
| 66 | //test string | ||
| 67 | if err = bm.Put("astaxie", "author", 10); err != nil { | ||
| 68 | t.Error("set Error", err) | ||
| 69 | } | ||
| 70 | if !bm.IsExist("astaxie") { | ||
| 71 | t.Error("check err") | ||
| 72 | } | ||
| 73 | |||
| 74 | if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" { | ||
| 75 | t.Error("get err") | ||
| 76 | } | ||
| 77 | // test clear all | ||
| 78 | if err = bm.ClearAll(); err != nil { | ||
| 79 | t.Error("clear all err") | ||
| 80 | } | ||
| 81 | } |
-
Please register or sign in to post a comment