Merge pull request #4247 from flycash/adt/cache

Adapter: cache API
This commit is contained in:
Ming Deng 2020-10-05 14:46:13 +08:00 committed by GitHub
commit ff7a8b966b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 1044 additions and 5 deletions

View File

@ -33,8 +33,7 @@ package cache
import (
"fmt"
"github.com/astaxie/beego/pkg/client/cache"
"time"
)
// Cache interface contains all behaviors for cache adapter.
@ -47,7 +46,26 @@ import (
// c.Incr("counter") // now is 1
// c.Incr("counter") // now is 2
// count := c.Get("counter").(int)
type Cache cache.Cache
type Cache interface {
// get cached value by key.
Get(key string) interface{}
// GetMulti is a batch version of Get.
GetMulti(keys []string) []interface{}
// set cached value with key and expire time.
Put(key string, val interface{}, timeout time.Duration) error
// delete cached value by key.
Delete(key string) error
// increase cached int value by key, as a counter.
Incr(key string) error
// decrease cached int value by key, as a counter.
Decr(key string) error
// check if cached value exists or not.
IsExist(key string) bool
// clear all cache.
ClearAll() error
// start gc routine based on config string settings.
StartAndGC(config string) error
}
// Instance is a function create a new Cache Instance
type Instance func() Cache

117
pkg/adapter/cache/cache_adapter.go vendored Normal file
View File

@ -0,0 +1,117 @@
// Copyright 2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"context"
"time"
"github.com/astaxie/beego/pkg/client/cache"
)
type newToOldCacheAdapter struct {
delegate cache.Cache
}
func (c *newToOldCacheAdapter) Get(key string) interface{} {
res, _ := c.delegate.Get(context.Background(), key)
return res
}
func (c *newToOldCacheAdapter) GetMulti(keys []string) []interface{} {
res, _ := c.delegate.GetMulti(context.Background(), keys)
return res
}
func (c *newToOldCacheAdapter) Put(key string, val interface{}, timeout time.Duration) error {
return c.delegate.Put(context.Background(), key, val, timeout)
}
func (c *newToOldCacheAdapter) Delete(key string) error {
return c.delegate.Delete(context.Background(), key)
}
func (c *newToOldCacheAdapter) Incr(key string) error {
return c.delegate.Incr(context.Background(), key)
}
func (c *newToOldCacheAdapter) Decr(key string) error {
return c.delegate.Decr(context.Background(), key)
}
func (c *newToOldCacheAdapter) IsExist(key string) bool {
res, err := c.delegate.IsExist(context.Background(), key)
return res && err == nil
}
func (c *newToOldCacheAdapter) ClearAll() error {
return c.delegate.ClearAll(context.Background())
}
func (c *newToOldCacheAdapter) StartAndGC(config string) error {
return c.delegate.StartAndGC(config)
}
func CreateNewToOldCacheAdapter(delegate cache.Cache) Cache {
return &newToOldCacheAdapter{
delegate: delegate,
}
}
type oldToNewCacheAdapter struct {
old Cache
}
func (o *oldToNewCacheAdapter) Get(ctx context.Context, key string) (interface{}, error) {
return o.old.Get(key), nil
}
func (o *oldToNewCacheAdapter) GetMulti(ctx context.Context, keys []string) ([]interface{}, error) {
return o.old.GetMulti(keys), nil
}
func (o *oldToNewCacheAdapter) Put(ctx context.Context, key string, val interface{}, timeout time.Duration) error {
return o.old.Put(key, val, timeout)
}
func (o *oldToNewCacheAdapter) Delete(ctx context.Context, key string) error {
return o.old.Delete(key)
}
func (o *oldToNewCacheAdapter) Incr(ctx context.Context, key string) error {
return o.old.Incr(key)
}
func (o *oldToNewCacheAdapter) Decr(ctx context.Context, key string) error {
return o.old.Decr(key)
}
func (o *oldToNewCacheAdapter) IsExist(ctx context.Context, key string) (bool, error) {
return o.old.IsExist(key), nil
}
func (o *oldToNewCacheAdapter) ClearAll(ctx context.Context) error {
return o.old.ClearAll()
}
func (o *oldToNewCacheAdapter) StartAndGC(config string) error {
return o.old.StartAndGC(config)
}
func CreateOldToNewAdapter(old Cache) cache.Cache {
return &oldToNewCacheAdapter{
old: old,
}
}

191
pkg/adapter/cache/cache_test.go vendored Normal file
View File

@ -0,0 +1,191 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"os"
"sync"
"testing"
"time"
)
func TestCacheIncr(t *testing.T) {
bm, err := NewCache("memory", `{"interval":20}`)
if err != nil {
t.Error("init err")
}
//timeoutDuration := 10 * time.Second
bm.Put("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")
}()
}
wg.Wait()
if bm.Get("edwardhey").(int) != 10 {
t.Error("Incr err")
}
}
func TestCache(t *testing.T) {
bm, err := NewCache("memory", `{"interval":20}`)
if err != nil {
t.Error("init err")
}
timeoutDuration := 10 * time.Second
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v := bm.Get("astaxie"); v.(int) != 1 {
t.Error("get err")
}
time.Sleep(30 * time.Second)
if bm.IsExist("astaxie") {
t.Error("check err")
}
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
t.Error("set Error", err)
}
if err = bm.Incr("astaxie"); err != nil {
t.Error("Incr Error", err)
}
if v := bm.Get("astaxie"); v.(int) != 2 {
t.Error("get err")
}
if err = bm.Decr("astaxie"); err != nil {
t.Error("Decr Error", err)
}
if v := bm.Get("astaxie"); v.(int) != 1 {
t.Error("get err")
}
bm.Delete("astaxie")
if bm.IsExist("astaxie") {
t.Error("delete err")
}
//test GetMulti
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v := bm.Get("astaxie"); v.(string) != "author" {
t.Error("get err")
}
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie1") {
t.Error("check err")
}
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
if len(vv) != 2 {
t.Error("GetMulti ERROR")
}
if vv[0].(string) != "author" {
t.Error("GetMulti ERROR")
}
if vv[1].(string) != "author1" {
t.Error("GetMulti ERROR")
}
}
func TestFileCache(t *testing.T) {
bm, err := NewCache("file", `{"CachePath":"cache","FileSuffix":".bin","DirectoryLevel":"2","EmbedExpiry":"0"}`)
if err != nil {
t.Error("init err")
}
timeoutDuration := 10 * time.Second
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v := bm.Get("astaxie"); v.(int) != 1 {
t.Error("get err")
}
if err = bm.Incr("astaxie"); err != nil {
t.Error("Incr Error", err)
}
if v := bm.Get("astaxie"); v.(int) != 2 {
t.Error("get err")
}
if err = bm.Decr("astaxie"); err != nil {
t.Error("Decr Error", err)
}
if v := bm.Get("astaxie"); v.(int) != 1 {
t.Error("get err")
}
bm.Delete("astaxie")
if bm.IsExist("astaxie") {
t.Error("delete err")
}
//test string
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v := bm.Get("astaxie"); v.(string) != "author" {
t.Error("get err")
}
//test GetMulti
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie1") {
t.Error("check err")
}
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
if len(vv) != 2 {
t.Error("GetMulti ERROR")
}
if vv[0].(string) != "author" {
t.Error("GetMulti ERROR")
}
if vv[1].(string) != "author1" {
t.Error("GetMulti ERROR")
}
os.RemoveAll("cache")
}

44
pkg/adapter/cache/conv.go vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"github.com/astaxie/beego/pkg/client/cache"
)
// GetString convert interface to string.
func GetString(v interface{}) string {
return cache.GetString(v)
}
// GetInt convert interface to int.
func GetInt(v interface{}) int {
return cache.GetInt(v)
}
// GetInt64 convert interface to int64.
func GetInt64(v interface{}) int64 {
return cache.GetInt64(v)
}
// GetFloat64 convert interface to float64.
func GetFloat64(v interface{}) float64 {
return cache.GetFloat64(v)
}
// GetBool convert interface to bool.
func GetBool(v interface{}) bool {
return cache.GetBool(v)
}

143
pkg/adapter/cache/conv_test.go vendored Normal file
View File

@ -0,0 +1,143 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"testing"
)
func TestGetString(t *testing.T) {
var t1 = "test1"
if "test1" != GetString(t1) {
t.Error("get string from string error")
}
var t2 = []byte("test2")
if "test2" != GetString(t2) {
t.Error("get string from byte array error")
}
var t3 = 1
if "1" != GetString(t3) {
t.Error("get string from int error")
}
var t4 int64 = 1
if "1" != GetString(t4) {
t.Error("get string from int64 error")
}
var t5 = 1.1
if "1.1" != GetString(t5) {
t.Error("get string from float64 error")
}
if "" != GetString(nil) {
t.Error("get string from nil error")
}
}
func TestGetInt(t *testing.T) {
var t1 = 1
if 1 != GetInt(t1) {
t.Error("get int from int error")
}
var t2 int32 = 32
if 32 != GetInt(t2) {
t.Error("get int from int32 error")
}
var t3 int64 = 64
if 64 != GetInt(t3) {
t.Error("get int from int64 error")
}
var t4 = "128"
if 128 != GetInt(t4) {
t.Error("get int from num string error")
}
if 0 != GetInt(nil) {
t.Error("get int from nil error")
}
}
func TestGetInt64(t *testing.T) {
var i int64 = 1
var t1 = 1
if i != GetInt64(t1) {
t.Error("get int64 from int error")
}
var t2 int32 = 1
if i != GetInt64(t2) {
t.Error("get int64 from int32 error")
}
var t3 int64 = 1
if i != GetInt64(t3) {
t.Error("get int64 from int64 error")
}
var t4 = "1"
if i != GetInt64(t4) {
t.Error("get int64 from num string error")
}
if 0 != GetInt64(nil) {
t.Error("get int64 from nil")
}
}
func TestGetFloat64(t *testing.T) {
var f = 1.11
var t1 float32 = 1.11
if f != GetFloat64(t1) {
t.Error("get float64 from float32 error")
}
var t2 = 1.11
if f != GetFloat64(t2) {
t.Error("get float64 from float64 error")
}
var t3 = "1.11"
if f != GetFloat64(t3) {
t.Error("get float64 from string error")
}
var f2 float64 = 1
var t4 = 1
if f2 != GetFloat64(t4) {
t.Error("get float64 from int error")
}
if 0 != GetFloat64(nil) {
t.Error("get float64 from nil error")
}
}
func TestGetBool(t *testing.T) {
var t1 = true
if !GetBool(t1) {
t.Error("get bool from bool error")
}
var t2 = "true"
if !GetBool(t2) {
t.Error("get bool from string error")
}
if GetBool(nil) {
t.Error("get bool from nil error")
}
}
func byteArrayEquals(a []byte, b []byte) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}

30
pkg/adapter/cache/file.go vendored Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"github.com/astaxie/beego/pkg/client/cache"
)
// NewFileCache Create new file cache with no config.
// the level and expiry need set in method StartAndGC as config string.
func NewFileCache() Cache {
// return &FileCache{CachePath:FileCachePath, FileSuffix:FileCacheFileSuffix}
return CreateNewToOldCacheAdapter(cache.NewFileCache())
}
func init() {
Register("file", NewFileCache)
}

44
pkg/adapter/cache/memcache/memcache.go vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package memcache for cache provider
//
// depend on github.com/bradfitz/gomemcache/memcache
//
// go install github.com/bradfitz/gomemcache/memcache
//
// Usage:
// import(
// _ "github.com/astaxie/beego/cache/memcache"
// "github.com/astaxie/beego/cache"
// )
//
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
//
// more docs http://beego.me/docs/module/cache.md
package memcache
import (
"github.com/astaxie/beego/pkg/adapter/cache"
"github.com/astaxie/beego/pkg/client/cache/memcache"
)
// NewMemCache create new memcache adapter.
func NewMemCache() cache.Cache {
return cache.CreateNewToOldCacheAdapter(memcache.NewMemCache())
}
func init() {
cache.Register("memcache", NewMemCache)
}

View File

@ -0,0 +1,114 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package memcache
import (
"fmt"
"os"
"strconv"
"testing"
"time"
"github.com/astaxie/beego/pkg/adapter/cache"
)
func TestMemcacheCache(t *testing.T) {
addr := os.Getenv("MEMCACHE_ADDR")
if addr == "" {
addr = "127.0.0.1:11211"
}
bm, err := cache.NewCache("memcache", fmt.Sprintf(`{"conn": "%s"}`, addr))
if err != nil {
t.Error("init err")
}
timeoutDuration := 10 * time.Second
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
time.Sleep(11 * time.Second)
if bm.IsExist("astaxie") {
t.Error("check err")
}
if err = bm.Put("astaxie", "1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
t.Error("get err")
}
if err = bm.Incr("astaxie"); err != nil {
t.Error("Incr Error", err)
}
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 2 {
t.Error("get err")
}
if err = bm.Decr("astaxie"); err != nil {
t.Error("Decr Error", err)
}
if v, err := strconv.Atoi(string(bm.Get("astaxie").([]byte))); err != nil || v != 1 {
t.Error("get err")
}
bm.Delete("astaxie")
if bm.IsExist("astaxie") {
t.Error("delete err")
}
// test string
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v := bm.Get("astaxie").([]byte); string(v) != "author" {
t.Error("get err")
}
// test GetMulti
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie1") {
t.Error("check err")
}
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
if len(vv) != 2 {
t.Error("GetMulti ERROR")
}
if string(vv[0].([]byte)) != "author" && string(vv[0].([]byte)) != "author1" {
t.Error("GetMulti ERROR")
}
if string(vv[1].([]byte)) != "author1" && string(vv[1].([]byte)) != "author" {
t.Error("GetMulti ERROR")
}
// test clear all
if err = bm.ClearAll(); err != nil {
t.Error("clear all err")
}
}

28
pkg/adapter/cache/memory.go vendored Normal file
View File

@ -0,0 +1,28 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cache
import (
"github.com/astaxie/beego/pkg/client/cache"
)
// NewMemoryCache returns a new MemoryCache.
func NewMemoryCache() Cache {
return CreateNewToOldCacheAdapter(cache.NewMemoryCache())
}
func init() {
Register("memory", NewMemoryCache)
}

49
pkg/adapter/cache/redis/redis.go vendored Normal file
View File

@ -0,0 +1,49 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package redis for cache provider
//
// depend on github.com/gomodule/redigo/redis
//
// go install github.com/gomodule/redigo/redis
//
// Usage:
// import(
// _ "github.com/astaxie/beego/cache/redis"
// "github.com/astaxie/beego/cache"
// )
//
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
//
// more docs http://beego.me/docs/module/cache.md
package redis
import (
"github.com/astaxie/beego/pkg/adapter/cache"
redis2 "github.com/astaxie/beego/pkg/client/cache/redis"
)
var (
// DefaultKey the collection name of redis for cache adapter.
DefaultKey = "beecacheRedis"
)
// NewRedisCache create new redis cache with default collection name.
func NewRedisCache() cache.Cache {
return cache.CreateNewToOldCacheAdapter(redis2.NewRedisCache())
}
func init() {
cache.Register("redis", NewRedisCache)
}

135
pkg/adapter/cache/redis/redis_test.go vendored Normal file
View File

@ -0,0 +1,135 @@
// Copyright 2014 beego Author. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package redis
import (
"fmt"
"os"
"testing"
"time"
"github.com/gomodule/redigo/redis"
"github.com/astaxie/beego/pkg/adapter/cache"
)
func TestRedisCache(t *testing.T) {
redisAddr := os.Getenv("REDIS_ADDR")
if redisAddr == "" {
redisAddr = "127.0.0.1:6379"
}
bm, err := cache.NewCache("redis", fmt.Sprintf(`{"conn": "%s"}`, redisAddr))
if err != nil {
t.Error("init err")
}
timeoutDuration := 10 * time.Second
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
time.Sleep(11 * time.Second)
if bm.IsExist("astaxie") {
t.Error("check err")
}
if err = bm.Put("astaxie", 1, timeoutDuration); err != nil {
t.Error("set Error", err)
}
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
t.Error("get err")
}
if err = bm.Incr("astaxie"); err != nil {
t.Error("Incr Error", err)
}
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 2 {
t.Error("get err")
}
if err = bm.Decr("astaxie"); err != nil {
t.Error("Decr Error", err)
}
if v, _ := redis.Int(bm.Get("astaxie"), err); v != 1 {
t.Error("get err")
}
bm.Delete("astaxie")
if bm.IsExist("astaxie") {
t.Error("delete err")
}
//test string
if err = bm.Put("astaxie", "author", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie") {
t.Error("check err")
}
if v, _ := redis.String(bm.Get("astaxie"), err); v != "author" {
t.Error("get err")
}
//test GetMulti
if err = bm.Put("astaxie1", "author1", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if !bm.IsExist("astaxie1") {
t.Error("check err")
}
vv := bm.GetMulti([]string{"astaxie", "astaxie1"})
if len(vv) != 2 {
t.Error("GetMulti ERROR")
}
if v, _ := redis.String(vv[0], nil); v != "author" {
t.Error("GetMulti ERROR")
}
if v, _ := redis.String(vv[1], nil); v != "author1" {
t.Error("GetMulti ERROR")
}
// test clear all
if err = bm.ClearAll(); err != nil {
t.Error("clear all err")
}
}
func TestCache_Scan(t *testing.T) {
timeoutDuration := 10 * time.Second
// init
bm, err := cache.NewCache("redis", `{"conn": "127.0.0.1:6379"}`)
if err != nil {
t.Error("init err")
}
// insert all
for i := 0; i < 10000; i++ {
if err = bm.Put(fmt.Sprintf("astaxie%d", i), fmt.Sprintf("author%d", i), timeoutDuration); err != nil {
t.Error("set Error", err)
}
}
// clear all
if err = bm.ClearAll(); err != nil {
t.Error("clear all err")
}
}

15
pkg/adapter/cache/ssdb/ssdb.go vendored Normal file
View File

@ -0,0 +1,15 @@
package ssdb
import (
"github.com/astaxie/beego/pkg/adapter/cache"
ssdb2 "github.com/astaxie/beego/pkg/client/cache/ssdb"
)
// NewSsdbCache create new ssdb adapter.
func NewSsdbCache() cache.Cache {
return cache.CreateNewToOldCacheAdapter(ssdb2.NewSsdbCache())
}
func init() {
cache.Register("ssdb", NewSsdbCache)
}

111
pkg/adapter/cache/ssdb/ssdb_test.go vendored Normal file
View File

@ -0,0 +1,111 @@
package ssdb
import (
"fmt"
"os"
"strconv"
"testing"
"time"
"github.com/astaxie/beego/pkg/adapter/cache"
)
func TestSsdbcacheCache(t *testing.T) {
ssdbAddr := os.Getenv("SSDB_ADDR")
if ssdbAddr == "" {
ssdbAddr = "127.0.0.1:8888"
}
ssdb, err := cache.NewCache("ssdb", fmt.Sprintf(`{"conn": "%s"}`, ssdbAddr))
if err != nil {
t.Error("init err")
}
// test put and exist
if ssdb.IsExist("ssdb") {
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 {
t.Error("set Error", err)
}
if !ssdb.IsExist("ssdb") {
t.Error("check err")
}
// Get test done
if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if v := ssdb.Get("ssdb"); v != "ssdb" {
t.Error("get Error")
}
//inc/dec test done
if err = ssdb.Put("ssdb", "2", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if err = ssdb.Incr("ssdb"); err != nil {
t.Error("incr Error", err)
}
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
t.Error("get err")
}
if err = ssdb.Decr("ssdb"); err != nil {
t.Error("decr error")
}
// test del
if err = ssdb.Put("ssdb", "3", timeoutDuration); err != nil {
t.Error("set Error", err)
}
if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 {
t.Error("get err")
}
if err := ssdb.Delete("ssdb"); err == nil {
if ssdb.IsExist("ssdb") {
t.Error("delete err")
}
}
//test string
if err = ssdb.Put("ssdb", "ssdb", -10*time.Second); err != nil {
t.Error("set Error", err)
}
if !ssdb.IsExist("ssdb") {
t.Error("check err")
}
if v := ssdb.Get("ssdb").(string); v != "ssdb" {
t.Error("get err")
}
//test GetMulti done
if err = ssdb.Put("ssdb1", "ssdb1", -10*time.Second); err != nil {
t.Error("set Error", err)
}
if !ssdb.IsExist("ssdb1") {
t.Error("check err")
}
vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"})
if len(vv) != 2 {
t.Error("getmulti error")
}
if vv[0].(string) != "ssdb" {
t.Error("getmulti error")
}
if vv[1].(string) != "ssdb1" {
t.Error("getmulti error")
}
// test clear all done
if err = ssdb.ClearAll(); err != nil {
t.Error("clear all err")
}
if ssdb.IsExist("ssdb") || ssdb.IsExist("ssdb1") {
t.Error("check err")
}
}

View File

@ -114,11 +114,11 @@ func (c *Captcha) Verify(id string, challenge string) (success bool) {
// NewCaptcha create a new captcha.Captcha
func NewCaptcha(urlPrefix string, store cache.Cache) *Captcha {
return (*Captcha)(captcha.NewCaptcha(urlPrefix, store))
return (*Captcha)(captcha.NewCaptcha(urlPrefix, cache.CreateOldToNewAdapter(store)))
}
// NewWithFilter create a new captcha.Captcha and auto AddFilter for serve captacha image
// and add a template func for output html
func NewWithFilter(urlPrefix string, store cache.Cache) *Captcha {
return (*Captcha)(captcha.NewWithFilter(urlPrefix, store))
return (*Captcha)(captcha.NewWithFilter(urlPrefix, cache.CreateOldToNewAdapter(store)))
}