499ee09d by astaxie

Merge pull request #1194 from zieckey/GetMulti

Add GetMulti method for Cache interface
2 parents 92806839 970f0b46
...@@ -47,6 +47,8 @@ import ( ...@@ -47,6 +47,8 @@ import (
47 type Cache interface { 47 type Cache interface {
48 // get cached value by key. 48 // get cached value by key.
49 Get(key string) interface{} 49 Get(key string) interface{}
50 // GetMulti is a batch version of Get.
51 GetMulti(keys []string) []interface{}
50 // set cached value with key and expire time. 52 // set cached value with key and expire time.
51 Put(key string, val interface{}, timeout int64) error 53 Put(key string, val interface{}, timeout int64) error
52 // delete cached value by key. 54 // delete cached value by key.
......
...@@ -65,6 +65,35 @@ func TestCache(t *testing.T) { ...@@ -65,6 +65,35 @@ func TestCache(t *testing.T) {
65 if bm.IsExist("astaxie") { 65 if bm.IsExist("astaxie") {
66 t.Error("delete err") 66 t.Error("delete err")
67 } 67 }
68
69 //test GetMulti
70 if err = bm.Put("astaxie", "author", 10); err != nil {
71 t.Error("set Error", err)
72 }
73 if !bm.IsExist("astaxie") {
74 t.Error("check err")
75 }
76 if v := bm.Get("astaxie"); v.(string) != "author" {
77 t.Error("get err")
78 }
79
80 if err = bm.Put("astaxie1", "author1", 10); err != nil {
81 t.Error("set Error", err)
82 }
83 if !bm.IsExist("astaxie1") {
84 t.Error("check err")
85 }
86
87 vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
88 if len(vv) != 2 {
89 t.Error("GetMulti ERROR")
90 }
91 if vv[0].(string) != "author" {
92 t.Error("GetMulti ERROR")
93 }
94 if vv[1].(string) != "author1" {
95 t.Error("GetMulti ERROR")
96 }
68 } 97 }
69 98
70 func TestFileCache(t *testing.T) { 99 func TestFileCache(t *testing.T) {
...@@ -102,6 +131,7 @@ func TestFileCache(t *testing.T) { ...@@ -102,6 +131,7 @@ func TestFileCache(t *testing.T) {
102 if bm.IsExist("astaxie") { 131 if bm.IsExist("astaxie") {
103 t.Error("delete err") 132 t.Error("delete err")
104 } 133 }
134
105 //test string 135 //test string
106 if err = bm.Put("astaxie", "author", 10); err != nil { 136 if err = bm.Put("astaxie", "author", 10); err != nil {
107 t.Error("set Error", err) 137 t.Error("set Error", err)
...@@ -109,9 +139,28 @@ func TestFileCache(t *testing.T) { ...@@ -109,9 +139,28 @@ func TestFileCache(t *testing.T) {
109 if !bm.IsExist("astaxie") { 139 if !bm.IsExist("astaxie") {
110 t.Error("check err") 140 t.Error("check err")
111 } 141 }
112
113 if v := bm.Get("astaxie"); v.(string) != "author" { 142 if v := bm.Get("astaxie"); v.(string) != "author" {
114 t.Error("get err") 143 t.Error("get err")
115 } 144 }
145
146 //test GetMulti
147 if err = bm.Put("astaxie1", "author1", 10); err != nil {
148 t.Error("set Error", err)
149 }
150 if !bm.IsExist("astaxie1") {
151 t.Error("check err")
152 }
153
154 vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
155 if len(vv) != 2 {
156 t.Error("GetMulti ERROR")
157 }
158 if vv[0].(string) != "author" {
159 t.Error("GetMulti ERROR")
160 }
161 if vv[1].(string) != "author1" {
162 t.Error("GetMulti ERROR")
163 }
164
116 os.RemoveAll("cache") 165 os.RemoveAll("cache")
117 } 166 }
......
...@@ -132,6 +132,16 @@ func (fc *FileCache) Get(key string) interface{} { ...@@ -132,6 +132,16 @@ func (fc *FileCache) Get(key string) interface{} {
132 return to.Data 132 return to.Data
133 } 133 }
134 134
135 // GetMulti gets values from file cache.
136 // if non-exist or expired, return empty string.
137 func (fc *FileCache) GetMulti(keys []string) []interface{} {
138 var rc []interface{}
139 for _, key := range keys {
140 rc = append(rc, fc.Get(key))
141 }
142 return rc
143 }
144
135 // Put value into file cache. 145 // Put value into file cache.
136 // timeout means how long to keep this file, unit of ms. 146 // timeout means how long to keep this file, unit of ms.
137 // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever. 147 // if timeout equals FileCacheEmbedExpiry(default is 0), cache this item forever.
......
...@@ -63,6 +63,32 @@ func (rc *MemcacheCache) Get(key string) interface{} { ...@@ -63,6 +63,32 @@ func (rc *MemcacheCache) Get(key string) interface{} {
63 return nil 63 return nil
64 } 64 }
65 65
66 // get value from memcache.
67 func (rc *MemcacheCache) GetMulti(keys []string) []interface{} {
68 size := len(keys)
69 var rv []interface{}
70 if rc.conn == nil {
71 if err := rc.connectInit(); err != nil {
72 for i := 0; i < size; i++ {
73 rv = append(rv, err)
74 }
75 return rv
76 }
77 }
78 mv, err := rc.conn.GetMulti(keys)
79 if err == nil {
80 for _, v := range mv {
81 rv = append(rv, string(v.Value))
82 }
83 return rv
84 } else {
85 for i := 0; i < size; i++ {
86 rv = append(rv, err)
87 }
88 return rv
89 }
90 }
91
66 // put value to memcache. only support string. 92 // put value to memcache. only support string.
67 func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error { 93 func (rc *MemcacheCache) Put(key string, val interface{}, timeout int64) error {
68 if rc.conn == nil { 94 if rc.conn == nil {
......
1 // Copyright 2014 beego Author. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package memcache
16
17 import (
18 _ "github.com/bradfitz/gomemcache/memcache"
19
20 "github.com/astaxie/beego/cache"
21 "strconv"
22 "testing"
23 "time"
24 )
25
26 func TestRedisCache(t *testing.T) {
27 bm, err := cache.NewCache("memcache", `{"conn": "127.0.0.1:11211"}`)
28 if err != nil {
29 t.Error("init err")
30 }
31 if err = bm.Put("astaxie", "1", 10); err != nil {
32 t.Error("set Error", err)
33 }
34 if !bm.IsExist("astaxie") {
35 t.Error("check err")
36 }
37
38 time.Sleep(10 * time.Second)
39
40 if bm.IsExist("astaxie") {
41 t.Error("check err")
42 }
43 if err = bm.Put("astaxie", "1", 10); err != nil {
44 t.Error("set Error", err)
45 }
46
47 if v, err := strconv.Atoi(bm.Get("astaxie").(string)); err != nil || v != 1 {
48 t.Error("get err")
49 }
50
51 if err = bm.Incr("astaxie"); err != nil {
52 t.Error("Incr Error", err)
53 }
54
55 if v, err := strconv.Atoi(bm.Get("astaxie").(string)); err != nil || v != 2 {
56 t.Error("get err")
57 }
58
59 if err = bm.Decr("astaxie"); err != nil {
60 t.Error("Decr Error", err)
61 }
62
63 if v, err := strconv.Atoi(bm.Get("astaxie").(string)); err != nil || v != 1 {
64 t.Error("get err")
65 }
66 bm.Delete("astaxie")
67 if bm.IsExist("astaxie") {
68 t.Error("delete err")
69 }
70
71 //test string
72 if err = bm.Put("astaxie", "author", 10); err != nil {
73 t.Error("set Error", err)
74 }
75 if !bm.IsExist("astaxie") {
76 t.Error("check err")
77 }
78
79 if v := bm.Get("astaxie").(string); v != "author" {
80 t.Error("get err")
81 }
82
83 //test GetMulti
84 if err = bm.Put("astaxie1", "author1", 10); err != nil {
85 t.Error("set Error", err)
86 }
87 if !bm.IsExist("astaxie1") {
88 t.Error("check err")
89 }
90
91 vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
92 if len(vv) != 2 {
93 t.Error("GetMulti ERROR")
94 }
95 if vv[0].(string) != "author" {
96 t.Error("GetMulti ERROR")
97 }
98 if vv[1].(string) != "author1" {
99 t.Error("GetMulti ERROR")
100 }
101
102 // test clear all
103 if err = bm.ClearAll(); err != nil {
104 t.Error("clear all err")
105 }
106 }
...@@ -64,6 +64,16 @@ func (bc *MemoryCache) Get(name string) interface{} { ...@@ -64,6 +64,16 @@ func (bc *MemoryCache) Get(name string) interface{} {
64 return nil 64 return nil
65 } 65 }
66 66
67 // GetMulti gets caches from memory.
68 // if non-existed or expired, return nil.
69 func (bc *MemoryCache) GetMulti(names []string) []interface{} {
70 var rc []interface{}
71 for _, name := range names {
72 rc = append(rc, bc.Get(name))
73 }
74 return rc
75 }
76
67 // Put cache to memory. 77 // Put cache to memory.
68 // if expired is 0, it will be cleaned by next gc operation ( default gc clock is 1 minute). 78 // if expired is 0, it will be cleaned by next gc operation ( default gc clock is 1 minute).
69 func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error { 79 func (bc *MemoryCache) Put(name string, value interface{}, expired int64) error {
......
...@@ -75,6 +75,39 @@ func (rc *RedisCache) Get(key string) interface{} { ...@@ -75,6 +75,39 @@ func (rc *RedisCache) Get(key string) interface{} {
75 return nil 75 return nil
76 } 76 }
77 77
78 // GetMulti get cache from redis.
79 func (rc *RedisCache) GetMulti(keys []string) []interface{} {
80 size := len(keys)
81 var rv []interface{}
82 c := rc.p.Get()
83 defer c.Close()
84 var err error
85 for _, key := range keys {
86 err = c.Send("GET", key)
87 if err != nil {
88 goto ERROR
89 }
90 }
91 if err = c.Flush(); err != nil {
92 goto ERROR
93 }
94 for i := 0; i < size; i++ {
95 if v, err := c.Receive(); err == nil {
96 rv = append(rv, v.([]byte))
97 } else {
98 rv = append(rv, err)
99 }
100 }
101 return rv
102 ERROR:
103 rv = rv[0:0]
104 for i := 0; i < size; i++ {
105 rv = append(rv, nil)
106 }
107
108 return rv
109 }
110
78 // put cache to redis. 111 // put cache to redis.
79 func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error { 112 func (rc *RedisCache) Put(key string, val interface{}, timeout int64) error {
80 var err error 113 var err error
......
...@@ -67,6 +67,7 @@ func TestRedisCache(t *testing.T) { ...@@ -67,6 +67,7 @@ func TestRedisCache(t *testing.T) {
67 if bm.IsExist("astaxie") { 67 if bm.IsExist("astaxie") {
68 t.Error("delete err") 68 t.Error("delete err")
69 } 69 }
70
70 //test string 71 //test string
71 if err = bm.Put("astaxie", "author", 10); err != nil { 72 if err = bm.Put("astaxie", "author", 10); err != nil {
72 t.Error("set Error", err) 73 t.Error("set Error", err)
...@@ -78,6 +79,26 @@ func TestRedisCache(t *testing.T) { ...@@ -78,6 +79,26 @@ func TestRedisCache(t *testing.T) {
78 if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" { 79 if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" {
79 t.Error("get err") 80 t.Error("get err")
80 } 81 }
82
83 //test GetMulti
84 if err = bm.Put("astaxie1", "author1", 10); err != nil {
85 t.Error("set Error", err)
86 }
87 if !bm.IsExist("astaxie1") {
88 t.Error("check err")
89 }
90
91 vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
92 if len(vv) != 2 {
93 t.Error("GetMulti ERROR")
94 }
95 if v, _ := redis.String(vv[0], nil); v != "author" {
96 t.Error("GetMulti ERROR")
97 }
98 if v, _ := redis.String(vv[1], nil); v != "author1" {
99 t.Error("GetMulti ERROR")
100 }
101
81 // test clear all 102 // test clear all
82 if err = bm.ClearAll(); err != nil { 103 if err = bm.ClearAll(); err != nil {
83 t.Error("clear all err") 104 t.Error("clear all err")
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!