diff --git a/pkg/client/cache/cache.go b/pkg/client/cache/cache.go index 049fb758..ddf246ab 100644 --- a/pkg/client/cache/cache.go +++ b/pkg/client/cache/cache.go @@ -32,6 +32,7 @@ package cache import ( + "context" "fmt" "time" ) @@ -48,21 +49,21 @@ import ( // count := c.Get("counter").(int) type Cache interface { // Get a cached value by key. - Get(key string) interface{} + Get(ctx context.Context, key string) (interface{}, error) // GetMulti is a batch version of Get. - GetMulti(keys []string) []interface{} + GetMulti(ctx context.Context, keys []string) ([]interface{}, error) // Set a cached value with key and expire time. - Put(key string, val interface{}, timeout time.Duration) error + Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error // Delete cached value by key. - Delete(key string) error + Delete(ctx context.Context, key string) error // Increment a cached int value by key, as a counter. - Incr(key string) error + Incr(ctx context.Context, key string) error // Decrement a cached int value by key, as a counter. - Decr(key string) error + Decr(ctx context.Context, key string) error // Check if a cached value exists or not. - IsExist(key string) bool + IsExist(ctx context.Context, key string) (bool, error) // Clear all cache. - ClearAll() error + ClearAll(ctx context.Context) error // Start gc routine based on config string settings. StartAndGC(config string) error } diff --git a/pkg/client/cache/cache_test.go b/pkg/client/cache/cache_test.go index 470c0a43..6066b72d 100644 --- a/pkg/client/cache/cache_test.go +++ b/pkg/client/cache/cache_test.go @@ -15,6 +15,7 @@ package cache import ( + "context" "os" "sync" "testing" @@ -26,19 +27,20 @@ func TestCacheIncr(t *testing.T) { if err != nil { t.Error("init err") } - //timeoutDuration := 10 * time.Second + // timeoutDuration := 10 * time.Second - bm.Put("edwardhey", 0, time.Second*20) + bm.Put(context.Background(), "edwardhey", 0, time.Second*20) wg := sync.WaitGroup{} wg.Add(10) for i := 0; i < 10; i++ { go func() { defer wg.Done() - bm.Incr("edwardhey") + bm.Incr(context.Background(), "edwardhey") }() } wg.Wait() - if bm.Get("edwardhey").(int) != 10 { + val, _ := bm.Get(context.Background(), "edwardhey") + if val.(int) != 10 { t.Error("Incr err") } } @@ -49,66 +51,66 @@ func TestCache(t *testing.T) { t.Error("init err") } timeoutDuration := 10 * time.Second - if err = bm.Put("astaxie", 1, timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v := bm.Get("astaxie"); v.(int) != 1 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 { t.Error("get err") } time.Sleep(30 * time.Second) - if bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("check err") } - if err = bm.Put("astaxie", 1, timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil { t.Error("set Error", err) } - if err = bm.Incr("astaxie"); err != nil { + if err = bm.Incr(context.Background(), "astaxie"); err != nil { t.Error("Incr Error", err) } - if v := bm.Get("astaxie"); v.(int) != 2 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 2 { t.Error("get err") } - if err = bm.Decr("astaxie"); err != nil { + if err = bm.Decr(context.Background(), "astaxie"); err != nil { t.Error("Decr Error", err) } - if v := bm.Get("astaxie"); v.(int) != 1 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 { t.Error("get err") } - bm.Delete("astaxie") - if bm.IsExist("astaxie") { + bm.Delete(context.Background(), "astaxie") + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("delete err") } - //test GetMulti - if err = bm.Put("astaxie", "author", timeoutDuration); err != nil { + // test GetMulti + if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v := bm.Get("astaxie"); v.(string) != "author" { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(string) != "author" { t.Error("get err") } - if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie1") { + if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res { t.Error("check err") } - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) + vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) if len(vv) != 2 { t.Error("GetMulti ERROR") } @@ -126,57 +128,57 @@ func TestFileCache(t *testing.T) { t.Error("init err") } timeoutDuration := 10 * time.Second - if err = bm.Put("astaxie", 1, timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v := bm.Get("astaxie"); v.(int) != 1 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 { t.Error("get err") } - if err = bm.Incr("astaxie"); err != nil { + if err = bm.Incr(context.Background(), "astaxie"); err != nil { t.Error("Incr Error", err) } - if v := bm.Get("astaxie"); v.(int) != 2 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 2 { t.Error("get err") } - if err = bm.Decr("astaxie"); err != nil { + if err = bm.Decr(context.Background(), "astaxie"); err != nil { t.Error("Decr Error", err) } - if v := bm.Get("astaxie"); v.(int) != 1 { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(int) != 1 { t.Error("get err") } - bm.Delete("astaxie") - if bm.IsExist("astaxie") { + bm.Delete(context.Background(), "astaxie") + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("delete err") } - //test string - if err = bm.Put("astaxie", "author", timeoutDuration); err != nil { + // test string + if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v := bm.Get("astaxie"); v.(string) != "author" { + if v, _ := bm.Get(context.Background(), "astaxie"); v.(string) != "author" { t.Error("get err") } - //test GetMulti - if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil { + // test GetMulti + if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie1") { + if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res { t.Error("check err") } - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) + vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) if len(vv) != 2 { t.Error("GetMulti ERROR") } diff --git a/pkg/client/cache/file.go b/pkg/client/cache/file.go index 0e5c44be..dc818258 100644 --- a/pkg/client/cache/file.go +++ b/pkg/client/cache/file.go @@ -16,6 +16,7 @@ package cache import ( "bytes" + "context" "crypto/md5" "encoding/gob" "encoding/hex" @@ -28,6 +29,8 @@ import ( "reflect" "strconv" "time" + + "github.com/pkg/errors" ) // FileCacheItem is basic unit of file cache adapter which @@ -120,33 +123,44 @@ func (fc *FileCache) getCacheFileName(key string) string { // Get value from file cache. // if nonexistent or expired return an empty string. -func (fc *FileCache) Get(key string) interface{} { +func (fc *FileCache) Get(ctx context.Context, key string) (interface{}, error) { fileData, err := FileGetContents(fc.getCacheFileName(key)) if err != nil { - return "" + return nil, err } + var to FileCacheItem - GobDecode(fileData, &to) - if to.Expired.Before(time.Now()) { - return "" + err = GobDecode(fileData, &to) + if err != nil { + return nil, err } - return to.Data + + if to.Expired.Before(time.Now()) { + return nil, errors.New("The key is expired") + } + return to.Data, nil } // GetMulti gets values from file cache. // if nonexistent or expired return an empty string. -func (fc *FileCache) GetMulti(keys []string) []interface{} { +func (fc *FileCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { var rc []interface{} for _, key := range keys { - rc = append(rc, fc.Get(key)) + val, err := fc.Get(context.Background(), key) + if err != nil { + rc = append(rc, err) + } else { + rc = append(rc, val) + } + } - return rc + return rc, nil } // Put value into file cache. // timeout: how long this file should be kept in ms // if timeout equals fc.EmbedExpiry(default is 0), cache this item forever. -func (fc *FileCache) Put(key string, val interface{}, timeout time.Duration) error { +func (fc *FileCache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { gob.Register(val) item := FileCacheItem{Data: val} @@ -164,7 +178,7 @@ func (fc *FileCache) Put(key string, val interface{}, timeout time.Duration) err } // Delete file cache value. -func (fc *FileCache) Delete(key string) error { +func (fc *FileCache) Delete(ctx context.Context, key string) error { filename := fc.getCacheFileName(key) if ok, _ := exists(filename); ok { return os.Remove(filename) @@ -174,39 +188,39 @@ func (fc *FileCache) Delete(key string) error { // Incr increases cached int value. // fc value is saved forever unless deleted. -func (fc *FileCache) Incr(key string) error { - data := fc.Get(key) +func (fc *FileCache) Incr(ctx context.Context, key string) error { + data, _ := fc.Get(context.Background(), key) var incr int if reflect.TypeOf(data).Name() != "int" { incr = 0 } else { incr = data.(int) + 1 } - fc.Put(key, incr, time.Duration(fc.EmbedExpiry)) + fc.Put(context.Background(), key, incr, time.Duration(fc.EmbedExpiry)) return nil } // Decr decreases cached int value. -func (fc *FileCache) Decr(key string) error { - data := fc.Get(key) +func (fc *FileCache) Decr(ctx context.Context, key string) error { + data, _ := fc.Get(context.Background(), key) var decr int if reflect.TypeOf(data).Name() != "int" || data.(int)-1 <= 0 { decr = 0 } else { decr = data.(int) - 1 } - fc.Put(key, decr, time.Duration(fc.EmbedExpiry)) + fc.Put(context.Background(), key, decr, time.Duration(fc.EmbedExpiry)) return nil } // IsExist checks if value exists. -func (fc *FileCache) IsExist(key string) bool { +func (fc *FileCache) IsExist(ctx context.Context, key string) (bool, error) { ret, _ := exists(fc.getCacheFileName(key)) - return ret + return ret, nil } // ClearAll cleans cached files (not implemented) -func (fc *FileCache) ClearAll() error { +func (fc *FileCache) ClearAll(context.Context) error { return nil } diff --git a/pkg/client/cache/memcache/memcache.go b/pkg/client/cache/memcache/memcache.go index 60712c2f..d3b7e767 100644 --- a/pkg/client/cache/memcache/memcache.go +++ b/pkg/client/cache/memcache/memcache.go @@ -30,6 +30,7 @@ package memcache import ( + "context" "encoding/json" "errors" "strings" @@ -52,28 +53,25 @@ func NewMemCache() cache.Cache { } // Get get value from memcache. -func (rc *Cache) Get(key string) interface{} { +func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) { if rc.conn == nil { if err := rc.connectInit(); err != nil { - return err + return nil, err } } if item, err := rc.conn.Get(key); err == nil { - return item.Value + return item.Value, nil + } else { + return nil, err } - return nil } // GetMulti gets a value from a key in memcache. -func (rc *Cache) GetMulti(keys []string) []interface{} { - size := len(keys) +func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { var rv []interface{} if rc.conn == nil { if err := rc.connectInit(); err != nil { - for i := 0; i < size; i++ { - rv = append(rv, err) - } - return rv + return rv, err } } mv, err := rc.conn.GetMulti(keys) @@ -81,16 +79,12 @@ func (rc *Cache) GetMulti(keys []string) []interface{} { for _, v := range mv { rv = append(rv, v.Value) } - return rv } - for i := 0; i < size; i++ { - rv = append(rv, err) - } - return rv + return rv, err } // Put puts a value into memcache. -func (rc *Cache) Put(key string, val interface{}, timeout time.Duration) error { +func (rc *Cache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -108,7 +102,7 @@ func (rc *Cache) Put(key string, val interface{}, timeout time.Duration) error { } // Delete deletes a value in memcache. -func (rc *Cache) Delete(key string) error { +func (rc *Cache) Delete(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -118,7 +112,7 @@ func (rc *Cache) Delete(key string) error { } // Incr increases counter. -func (rc *Cache) Incr(key string) error { +func (rc *Cache) Incr(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -129,7 +123,7 @@ func (rc *Cache) Incr(key string) error { } // Decr decreases counter. -func (rc *Cache) Decr(key string) error { +func (rc *Cache) Decr(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -140,18 +134,18 @@ func (rc *Cache) Decr(key string) error { } // IsExist checks if a value exists in memcache. -func (rc *Cache) IsExist(key string) bool { +func (rc *Cache) IsExist(ctx context.Context, key string) (bool, error) { if rc.conn == nil { if err := rc.connectInit(); err != nil { - return false + return false, err } } _, err := rc.conn.Get(key) - return err == nil + return err == nil, err } // ClearAll clears all cache in memcache. -func (rc *Cache) ClearAll() error { +func (rc *Cache) ClearAll(context.Context) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err diff --git a/pkg/client/cache/memcache/memcache_test.go b/pkg/client/cache/memcache/memcache_test.go index df2ba37f..64679671 100644 --- a/pkg/client/cache/memcache/memcache_test.go +++ b/pkg/client/cache/memcache/memcache_test.go @@ -15,15 +15,15 @@ package memcache import ( + "context" "fmt" "os" - - _ "github.com/bradfitz/gomemcache/memcache" - "strconv" "testing" "time" + _ "github.com/bradfitz/gomemcache/memcache" + "github.com/astaxie/beego/pkg/client/cache" ) @@ -39,67 +39,71 @@ func TestMemcacheCache(t *testing.T) { t.Error("init err") } timeoutDuration := 10 * time.Second - if err = bm.Put("astaxie", "1", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", "1", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } time.Sleep(11 * time.Second) - if bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("check err") } - if err = bm.Put("astaxie", "1", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", "1", timeoutDuration); err != nil { t.Error("set Error", err) } - if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 { + val, _ := bm.Get(context.Background(), "astaxie") + if v, err := strconv.Atoi(string(val.([]byte))); err != nil || v != 1 { t.Error("get err") } - if err = bm.Incr("astaxie"); err != nil { + if err = bm.Incr(context.Background(), "astaxie"); err != nil { t.Error("Incr Error", err) } - if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 2 { + val, _ = bm.Get(context.Background(), "astaxie") + if v, err := strconv.Atoi(string(val.([]byte))); err != nil || v != 2 { t.Error("get err") } - if err = bm.Decr("astaxie"); err != nil { + if err = bm.Decr(context.Background(), "astaxie"); err != nil { t.Error("Decr Error", err) } - if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 { + val, _ = bm.Get(context.Background(), "astaxie") + if v, err := strconv.Atoi(string(val.([]byte))); err != nil || v != 1 { t.Error("get err") } - bm.Delete("astaxie") - if bm.IsExist("astaxie") { + bm.Delete(context.Background(), "astaxie") + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("delete err") } // test string - if err = bm.Put("astaxie", "author", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v := bm.Get("astaxie").([]byte); string(v) != "author" { + val, _ = bm.Get(context.Background(), "astaxie") + if v := val.([]byte); string(v) != "author" { t.Error("get err") } // test GetMulti - if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie1") { + if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res { t.Error("check err") } - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) + vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) if len(vv) != 2 { t.Error("GetMulti ERROR") } @@ -111,7 +115,7 @@ func TestMemcacheCache(t *testing.T) { } // test clear all - if err = bm.ClearAll(); err != nil { + if err = bm.ClearAll(context.Background()); err != nil { t.Error("clear all err") } } diff --git a/pkg/client/cache/memory.go b/pkg/client/cache/memory.go index c0e35c6c..6f87ec08 100644 --- a/pkg/client/cache/memory.go +++ b/pkg/client/cache/memory.go @@ -15,6 +15,7 @@ package cache import ( + "context" "encoding/json" "errors" "sync" @@ -58,50 +59,55 @@ func NewMemoryCache() Cache { // Get returns cache from memory. // If non-existent or expired, return nil. -func (bc *MemoryCache) Get(name string) interface{} { +func (bc *MemoryCache) Get(ctx context.Context, key string) (interface{}, error) { bc.RLock() defer bc.RUnlock() - if itm, ok := bc.items[name]; ok { + if itm, ok := bc.items[key]; ok { if itm.isExpire() { - return nil + return nil, errors.New("the key is expired") } - return itm.val + return itm.val, nil } - return nil + return nil, nil } // GetMulti gets caches from memory. // If non-existent or expired, return nil. -func (bc *MemoryCache) GetMulti(names []string) []interface{} { +func (bc *MemoryCache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { var rc []interface{} - for _, name := range names { - rc = append(rc, bc.Get(name)) + for _, name := range keys { + val, err := bc.Get(context.Background(), name) + if err != nil { + rc = append(rc, err) + } else { + rc = append(rc, val) + } } - return rc + return rc, nil } // Put puts cache into memory. // If lifespan is 0, it will never overwrite this value unless restarted -func (bc *MemoryCache) Put(name string, value interface{}, lifespan time.Duration) error { +func (bc *MemoryCache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { bc.Lock() defer bc.Unlock() - bc.items[name] = &MemoryItem{ - val: value, + bc.items[key] = &MemoryItem{ + val: val, createdTime: time.Now(), - lifespan: lifespan, + lifespan: timeout, } return nil } // Delete cache in memory. -func (bc *MemoryCache) Delete(name string) error { +func (bc *MemoryCache) Delete(ctx context.Context, key string) error { bc.Lock() defer bc.Unlock() - if _, ok := bc.items[name]; !ok { + if _, ok := bc.items[key]; !ok { return errors.New("key not exist") } - delete(bc.items, name) - if _, ok := bc.items[name]; ok { + delete(bc.items, key) + if _, ok := bc.items[key]; ok { return errors.New("delete key error") } return nil @@ -109,7 +115,7 @@ func (bc *MemoryCache) Delete(name string) error { // Incr increases cache counter in memory. // Supports int,int32,int64,uint,uint32,uint64. -func (bc *MemoryCache) Incr(key string) error { +func (bc *MemoryCache) Incr(ctx context.Context, key string) error { bc.Lock() defer bc.Unlock() itm, ok := bc.items[key] @@ -136,7 +142,7 @@ func (bc *MemoryCache) Incr(key string) error { } // Decr decreases counter in memory. -func (bc *MemoryCache) Decr(key string) error { +func (bc *MemoryCache) Decr(ctx context.Context, key string) error { bc.Lock() defer bc.Unlock() itm, ok := bc.items[key] @@ -175,17 +181,17 @@ func (bc *MemoryCache) Decr(key string) error { } // IsExist checks if cache exists in memory. -func (bc *MemoryCache) IsExist(name string) bool { +func (bc *MemoryCache) IsExist(ctx context.Context, key string) (bool, error) { bc.RLock() defer bc.RUnlock() - if v, ok := bc.items[name]; ok { - return !v.isExpire() + if v, ok := bc.items[key]; ok { + return !v.isExpire(), nil } - return false + return false, nil } // ClearAll deletes all cache in memory. -func (bc *MemoryCache) ClearAll() error { +func (bc *MemoryCache) ClearAll(context.Context) error { bc.Lock() defer bc.Unlock() bc.items = make(map[string]*MemoryItem) diff --git a/pkg/client/cache/redis/redis.go b/pkg/client/cache/redis/redis.go index 2cd20503..e2785297 100644 --- a/pkg/client/cache/redis/redis.go +++ b/pkg/client/cache/redis/redis.go @@ -30,6 +30,7 @@ package redis import ( + "context" "encoding/json" "errors" "fmt" @@ -83,63 +84,60 @@ func (rc *Cache) associate(originKey interface{}) string { } // Get cache from redis. -func (rc *Cache) Get(key string) interface{} { +func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) { if v, err := rc.do("GET", key); err == nil { - return v + return v, nil + } else { + return nil, err } - return nil } // GetMulti gets cache from redis. -func (rc *Cache) GetMulti(keys []string) []interface{} { +func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { c := rc.p.Get() defer c.Close() var args []interface{} for _, key := range keys { args = append(args, rc.associate(key)) } - values, err := redis.Values(c.Do("MGET", args...)) - if err != nil { - return nil - } - return values + return redis.Values(c.Do("MGET", args...)) } // Put puts cache into redis. -func (rc *Cache) Put(key string, val interface{}, timeout time.Duration) error { +func (rc *Cache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { _, err := rc.do("SETEX", key, int64(timeout/time.Second), val) return err } // Delete deletes a key's cache in redis. -func (rc *Cache) Delete(key string) error { +func (rc *Cache) Delete(ctx context.Context, key string) error { _, err := rc.do("DEL", key) return err } // IsExist checks cache's existence in redis. -func (rc *Cache) IsExist(key string) bool { +func (rc *Cache) IsExist(ctx context.Context, key string) (bool, error) { v, err := redis.Bool(rc.do("EXISTS", key)) if err != nil { - return false + return false, err } - return v + return v, nil } // Incr increases a key's counter in redis. -func (rc *Cache) Incr(key string) error { +func (rc *Cache) Incr(ctx context.Context, key string) error { _, err := redis.Bool(rc.do("INCRBY", key, 1)) return err } // Decr decreases a key's counter in redis. -func (rc *Cache) Decr(key string) error { +func (rc *Cache) Decr(ctx context.Context, key string) error { _, err := redis.Bool(rc.do("INCRBY", key, -1)) return err } // ClearAll deletes all cache in the redis collection -func (rc *Cache) ClearAll() error { +func (rc *Cache) ClearAll(context.Context) error { cachedKeys, err := rc.Scan(rc.key + ":*") if err != nil { return err diff --git a/pkg/client/cache/redis/redis_test.go b/pkg/client/cache/redis/redis_test.go index dc0ca40f..f7308365 100644 --- a/pkg/client/cache/redis/redis_test.go +++ b/pkg/client/cache/redis/redis_test.go @@ -15,6 +15,7 @@ package redis import ( + "context" "fmt" "os" "testing" @@ -38,67 +39,70 @@ func TestRedisCache(t *testing.T) { t.Error("init err") } timeoutDuration := 10 * time.Second - if err = bm.Put("astaxie", 1, timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } time.Sleep(11 * time.Second) - if bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("check err") } - if err = bm.Put("astaxie", 1, timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", 1, timeoutDuration); err != nil { t.Error("set Error", err) } - if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { + val, _ := bm.Get(context.Background(), "astaxie") + if v, _ := redis.Int(val, err); v != 1 { t.Error("get err") } - if err = bm.Incr("astaxie"); err != nil { + if err = bm.Incr(context.Background(), "astaxie"); err != nil { t.Error("Incr Error", err) } - - if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 { + val, _ = bm.Get(context.Background(), "astaxie") + if v, _ := redis.Int(val, err); v != 2 { t.Error("get err") } - if err = bm.Decr("astaxie"); err != nil { + if err = bm.Decr(context.Background(), "astaxie"); err != nil { t.Error("Decr Error", err) } - if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 { + val, _ = bm.Get(context.Background(), "astaxie") + if v, _ := redis.Int(val, err); v != 1 { t.Error("get err") } - bm.Delete("astaxie") - if bm.IsExist("astaxie") { + bm.Delete(context.Background(), "astaxie") + if res, _ := bm.IsExist(context.Background(), "astaxie"); res { t.Error("delete err") } // test string - if err = bm.Put("astaxie", "author", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie", "author", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie") { + if res, _ := bm.IsExist(context.Background(), "astaxie"); !res { t.Error("check err") } - if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" { + val, _ = bm.Get(context.Background(), "astaxie") + if v, _ := redis.String(val, err); v != "author" { t.Error("get err") } // test GetMulti - if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil { + if err = bm.Put(context.Background(), "astaxie1", "author1", timeoutDuration); err != nil { t.Error("set Error", err) } - if !bm.IsExist("astaxie1") { + if res, _ := bm.IsExist(context.Background(), "astaxie1"); !res { t.Error("check err") } - vv := bm.GetMulti([]string{"astaxie", "astaxie1"}) + vv, _ := bm.GetMulti(context.Background(), []string{"astaxie", "astaxie1"}) if len(vv) != 2 { t.Error("GetMulti ERROR") } @@ -110,7 +114,7 @@ func TestRedisCache(t *testing.T) { } // test clear all - if err = bm.ClearAll(); err != nil { + if err = bm.ClearAll(context.Background()); err != nil { t.Error("clear all err") } } @@ -130,7 +134,7 @@ func TestCache_Scan(t *testing.T) { } // insert all for i := 0; i < 100; i++ { - if err = bm.Put(fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil { + if err = bm.Put(context.Background(), fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil { t.Error("set Error", err) } } @@ -144,7 +148,7 @@ func TestCache_Scan(t *testing.T) { assert.Equal(t, 100, len(keys), "scan all error") // clear all - if err = bm.ClearAll(); err != nil { + if err = bm.ClearAll(context.Background()); err != nil { t.Error("clear all err") } diff --git a/pkg/client/cache/ssdb/ssdb.go b/pkg/client/cache/ssdb/ssdb.go index 10ff72b0..2e4f2815 100644 --- a/pkg/client/cache/ssdb/ssdb.go +++ b/pkg/client/cache/ssdb/ssdb.go @@ -1,6 +1,7 @@ package ssdb import ( + "context" "encoding/json" "errors" "strconv" @@ -24,29 +25,26 @@ func NewSsdbCache() cache.Cache { } // Get gets a key's value from memcache. -func (rc *Cache) Get(key string) interface{} { +func (rc *Cache) Get(ctx context.Context, key string) (interface{}, error) { if rc.conn == nil { if err := rc.connectInit(); err != nil { - return nil + return nil, nil } } value, err := rc.conn.Get(key) if err == nil { - return value + return value, nil } - return nil + return nil, nil } -// GetMulti gets one or keys values from memcache. -func (rc *Cache) GetMulti(keys []string) []interface{} { +// GetMulti gets one or keys values from ssdb. +func (rc *Cache) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) { size := len(keys) var values []interface{} if rc.conn == nil { if err := rc.connectInit(); err != nil { - for i := 0; i < size; i++ { - values = append(values, err) - } - return values + return values, err } } res, err := rc.conn.Do("multi_get", keys) @@ -55,12 +53,12 @@ func (rc *Cache) GetMulti(keys []string) []interface{} { for i := 1; i < resSize; i += 2 { values = append(values, res[i+1]) } - return values + return values, nil } for i := 0; i < size; i++ { values = append(values, err) } - return values + return values, nil } // DelMulti deletes one or more keys from memcache @@ -76,13 +74,13 @@ func (rc *Cache) DelMulti(keys []string) error { // Put puts value into memcache. // value: must be of type string -func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error { +func (rc *Cache) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err } } - v, ok := value.(string) + v, ok := val.(string) if !ok { return errors.New("value must string") } @@ -104,7 +102,7 @@ func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error } // Delete deletes a value in memcache. -func (rc *Cache) Delete(key string) error { +func (rc *Cache) Delete(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -115,7 +113,7 @@ func (rc *Cache) Delete(key string) error { } // Incr increases a key's counter. -func (rc *Cache) Incr(key string) error { +func (rc *Cache) Incr(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -126,7 +124,7 @@ func (rc *Cache) Incr(key string) error { } // Decr decrements a key's counter. -func (rc *Cache) Decr(key string) error { +func (rc *Cache) Decr(ctx context.Context, key string) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err @@ -137,25 +135,25 @@ func (rc *Cache) Decr(key string) error { } // IsExist checks if a key exists in memcache. -func (rc *Cache) IsExist(key string) bool { +func (rc *Cache) IsExist(ctx context.Context, key string) (bool, error) { if rc.conn == nil { if err := rc.connectInit(); err != nil { - return false + return false, err } } resp, err := rc.conn.Do("exists", key) if err != nil { - return false + return false, err } if len(resp) == 2 && resp[1] == "1" { - return true + return true, nil } - return false + return false, nil } // ClearAll clears all cached items in memcache. -func (rc *Cache) ClearAll() error { +func (rc *Cache) ClearAll(context.Context) error { if rc.conn == nil { if err := rc.connectInit(); err != nil { return err diff --git a/pkg/client/cache/ssdb/ssdb_test.go b/pkg/client/cache/ssdb/ssdb_test.go index bd6ede4e..f675d1ab 100644 --- a/pkg/client/cache/ssdb/ssdb_test.go +++ b/pkg/client/cache/ssdb/ssdb_test.go @@ -1,6 +1,7 @@ package ssdb import ( + "context" "fmt" "os" "strconv" @@ -23,75 +24,78 @@ func TestSsdbcacheCache(t *testing.T) { } // test put and exist - if ssdb.IsExist("ssdb") { + if res, _ := ssdb.IsExist(context.Background(), "ssdb"); res { t.Error("check err") } timeoutDuration := 10 * time.Second - //timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent - if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil { + // timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent + if err = ssdb.Put(context.Background(), "ssdb", "ssdb", timeoutDuration); err != nil { t.Error("set Error", err) } - if !ssdb.IsExist("ssdb") { + if res, _ := ssdb.IsExist(context.Background(), "ssdb"); !res { t.Error("check err") } // Get test done - if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil { + if err = ssdb.Put(context.Background(), "ssdb", "ssdb", timeoutDuration); err != nil { t.Error("set Error", err) } - if v := ssdb.Get("ssdb"); v != "ssdb" { + if v, _ := ssdb.Get(context.Background(), "ssdb"); v != "ssdb" { t.Error("get Error") } - //inc/dec test done - if err = ssdb.Put("ssdb", "2", timeoutDuration); err != nil { + // inc/dec test done + if err = ssdb.Put(context.Background(), "ssdb", "2", timeoutDuration); err != nil { t.Error("set Error", err) } - if err = ssdb.Incr("ssdb"); err != nil { + if err = ssdb.Incr(context.Background(), "ssdb"); err != nil { t.Error("incr Error", err) } - if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 { + val, _ := ssdb.Get(context.Background(), "ssdb") + if v, err := strconv.Atoi(val.(string)); err != nil || v != 3 { t.Error("get err") } - if err = ssdb.Decr("ssdb"); err != nil { + if err = ssdb.Decr(context.Background(), "ssdb"); err != nil { t.Error("decr error") } // test del - if err = ssdb.Put("ssdb", "3", timeoutDuration); err != nil { + if err = ssdb.Put(context.Background(), "ssdb", "3", timeoutDuration); err != nil { t.Error("set Error", err) } - if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 { + + val, _ = ssdb.Get(context.Background(), "ssdb") + if v, err := strconv.Atoi(val.(string)); err != nil || v != 3 { t.Error("get err") } - if err := ssdb.Delete("ssdb"); err == nil { - if ssdb.IsExist("ssdb") { + if err := ssdb.Delete(context.Background(), "ssdb"); err == nil { + if e, _ := ssdb.IsExist(context.Background(), "ssdb"); e { t.Error("delete err") } } - //test string - if err = ssdb.Put("ssdb", "ssdb", -10*time.Second); err != nil { + // test string + if err = ssdb.Put(context.Background(), "ssdb", "ssdb", -10*time.Second); err != nil { t.Error("set Error", err) } - if !ssdb.IsExist("ssdb") { + if res, _ := ssdb.IsExist(context.Background(), "ssdb"); !res { t.Error("check err") } - if v := ssdb.Get("ssdb").(string); v != "ssdb" { + if v, _ := ssdb.Get(context.Background(), "ssdb"); v.(string) != "ssdb" { t.Error("get err") } - //test GetMulti done - if err = ssdb.Put("ssdb1", "ssdb1", -10*time.Second); err != nil { + // test GetMulti done + if err = ssdb.Put(context.Background(), "ssdb1", "ssdb1", -10*time.Second); err != nil { t.Error("set Error", err) } - if !ssdb.IsExist("ssdb1") { + if res, _ := ssdb.IsExist(context.Background(), "ssdb1"); !res { t.Error("check err") } - vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"}) + vv, _ := ssdb.GetMulti(context.Background(), []string{"ssdb", "ssdb1"}) if len(vv) != 2 { t.Error("getmulti error") } @@ -103,10 +107,12 @@ func TestSsdbcacheCache(t *testing.T) { } // test clear all done - if err = ssdb.ClearAll(); err != nil { + if err = ssdb.ClearAll(context.Background()); err != nil { t.Error("clear all err") } - if ssdb.IsExist("ssdb") || ssdb.IsExist("ssdb1") { + e1, _ := ssdb.IsExist(context.Background(), "ssdb") + e2, _ := ssdb.IsExist(context.Background(), "ssdb1") + if e1 || e2 { t.Error("check err") } } diff --git a/pkg/server/web/captcha/captcha.go b/pkg/server/web/captcha/captcha.go index 2c60f23a..36bc0fcb 100644 --- a/pkg/server/web/captcha/captcha.go +++ b/pkg/server/web/captcha/captcha.go @@ -59,6 +59,7 @@ package captcha import ( + context2 "context" "fmt" "html/template" "net/http" @@ -137,14 +138,15 @@ func (c *Captcha) Handler(ctx *context.Context) { if len(ctx.Input.Query("reload")) > 0 { chars = c.genRandChars() - if err := c.store.Put(key, chars, c.Expiration); err != nil { + if err := c.store.Put(context2.Background(), key, chars, c.Expiration); err != nil { ctx.Output.SetStatus(500) ctx.WriteString("captcha reload error") logs.Error("Reload Create Captcha Error:", err) return } } else { - if v, ok := c.store.Get(key).([]byte); ok { + val, _ := c.store.Get(context2.Background(), key) + if v, ok := val.([]byte); ok { chars = v } else { ctx.Output.SetStatus(404) @@ -183,7 +185,7 @@ func (c *Captcha) CreateCaptcha() (string, error) { chars := c.genRandChars() // save to store - if err := c.store.Put(c.key(id), chars, c.Expiration); err != nil { + if err := c.store.Put(context2.Background(), c.key(id), chars, c.Expiration); err != nil { return "", err } @@ -205,8 +207,8 @@ func (c *Captcha) Verify(id string, challenge string) (success bool) { var chars []byte key := c.key(id) - - if v, ok := c.store.Get(key).([]byte); ok { + val, _ := c.store.Get(context2.Background(), key) + if v, ok := val.([]byte); ok { chars = v } else { return @@ -214,7 +216,7 @@ func (c *Captcha) Verify(id string, challenge string) (success bool) { defer func() { // finally remove it - c.store.Delete(key) + c.store.Delete(context2.Background(), key) }() if len(chars) != len(challenge) { @@ -271,9 +273,9 @@ func NewWithFilter(urlPrefix string, store Storage) *Captcha { type Storage interface { // Get a cached value by key. - Get(key string) interface{} + Get(ctx context2.Context, key string) (interface{}, error) // Set a cached value with key and expire time. - Put(key string, val interface{}, timeout time.Duration) error + Put(ctx context2.Context, key string, val interface{}, timeout time.Duration) error // Delete cached value by key. - Delete(key string) error + Delete(ctx context2.Context, key string) error }