diff --git a/gcache/adapter_local.go b/gcache/adapter_local.go index 126b033..4cd5c88 100644 --- a/gcache/adapter_local.go +++ b/gcache/adapter_local.go @@ -7,4 +7,42 @@ package gcache +import ( + "sync" + "time" + + "git.hexq.cn/tiglog/golib/helper" +) + +const default_cache_size = 1024 + // 本地内存缓存 +type localCacheAdapter struct { + mu sync.Mutex + data map[string][]byte +} + +func NewLocalCacheAdapter() ICacheAdapter { + return &localCacheAdapter{ + data: make(map[string][]byte, default_cache_size), + } +} + +func (c *localCacheAdapter) Get(key string, dest interface{}) error { + val, ok := c.data[key] + if ok { + helper.Scan(val, dest) + } + return nil +} + +func (c *localCacheAdapter) Set(key string, val interface{}, ttl time.Duration) error { + return nil +} + +func (c *localCacheAdapter) Has(key string) bool { + return false +} +func (c *localCacheAdapter) Del(keys ...string) (int64, error) { + return 0, nil +} diff --git a/gcache/adapter_redis.go b/gcache/adapter_redis.go index 946996d..adfaf3d 100644 --- a/gcache/adapter_redis.go +++ b/gcache/adapter_redis.go @@ -7,4 +7,46 @@ package gcache +import ( + "context" + "sync" + "time" + + "github.com/go-redis/redis/v8" +) + // 使用 redis 服务缓存 +type redisCacheAdapter struct { + mu sync.Mutex + redis *redis.Client +} + +func NewRedisCacheAdapter(rds *redis.Client) ICacheAdapter { + return &redisCacheAdapter{ + redis: rds, + } +} + +func (c *redisCacheAdapter) Get(key string, dest interface{}) error { + cmd := c.redis.Get(context.Background(), key) + return cmd.Scan(dest) +} + +func (c *redisCacheAdapter) Set(key string, val interface{}, ttl time.Duration) error { + cmd := c.redis.Set(context.Background(), key, val, ttl) + return cmd.Err() +} + +func (c *redisCacheAdapter) Has(key string) bool { + cmd := c.redis.Exists(context.Background(), key) + result, _ := cmd.Result() + if result == 1 { + return true + } + return false +} + +func (c *redisCacheAdapter) Del(keys ...string) (int64, error) { + cmd := c.redis.Del(context.Background(), keys...) + return cmd.Result() +} diff --git a/gcache/cache.go b/gcache/cache.go index b1af227..cdec02e 100644 --- a/gcache/cache.go +++ b/gcache/cache.go @@ -7,10 +7,51 @@ package gcache +import ( + "sync" + "time" + + "github.com/go-redis/redis/v8" +) + type Engine struct { - ICacheAdapter + client ICacheAdapter } +var once sync.Once + +var engine *Engine + func New(adapter ICacheAdapter) *Engine { - return &Engine{adapter} + once.Do(func() { + engine = &Engine{ + client: adapter, + } + }) + return engine +} + +func NewWithRedis(rds *redis.Client) *Engine { + once.Do(func() { + engine = &Engine{ + client: NewRedisCacheAdapter(rds), + } + }) + return engine +} + +func (e *Engine) Get(key string, dest interface{}) error { + return e.client.Get(key, dest) +} + +func (e *Engine) Set(key string, val interface{}, ttl time.Duration) error { + return e.client.Set(key, val, ttl) +} + +func (e *Engine) Has(key string) bool { + return e.client.Has(key) +} + +func (e *Engine) Del(keys ...string) (int64, error) { + return e.client.Del(keys...) } diff --git a/gcache/cache_contract.go b/gcache/cache_contract.go index cebcaeb..d513a8b 100644 --- a/gcache/cache_contract.go +++ b/gcache/cache_contract.go @@ -10,9 +10,8 @@ package gcache import "time" type ICacheAdapter interface { - Get(key string) (string, error) + Get(key string, dest interface{}) error Set(key string, val interface{}, exp time.Duration) error - Del(keys ...string) int64 + Del(keys ...string) (int64, error) Has(key string) bool - End() } diff --git a/gcache/cache_test.go b/gcache/cache_test.go new file mode 100644 index 0000000..f492a12 --- /dev/null +++ b/gcache/cache_test.go @@ -0,0 +1,70 @@ +// +// cache_test.go +// Copyright (C) 2023 tiglog +// +// Distributed under terms of the MIT license. +// + +package gcache_test + +import ( + "context" + "fmt" + "os" + "testing" + "time" + + "git.hexq.cn/tiglog/golib/gcache" + "git.hexq.cn/tiglog/golib/gtest" + "github.com/go-redis/redis/v8" +) + +func getRedis() *redis.Client { + opt, _ := redis.ParseURL(os.Getenv("REDIS_URL")) + return redis.NewClient(opt) +} + +func TestRedis(t *testing.T) { + rds := getRedis() + cmd := rds.Ping(context.Background()) + ret, err := cmd.Result() + gtest.Nil(t, err) + fmt.Println(ret) +} + +func TestCacheNew(t *testing.T) { + rds := getRedis() + cm1 := gcache.NewWithRedis(rds) + cm2 := gcache.NewWithRedis(rds) + gtest.Equal(t, cm1, cm2) +} +func TestRedisAdapter(t *testing.T) { + rds := getRedis() + cm := gcache.NewWithRedis(rds) + key := "foo" + cm.Del(key) + r1 := cm.Has(key) + gtest.False(t, r1) + + var err error + val1 := "bar" + err = cm.Set(key, val1, time.Second) + gtest.Nil(t, err) + + var r2 string + err = cm.Get(key, &r2) + gtest.Nil(t, err) + gtest.Equal(t, val1, r2) + + val2 := 2 + err = cm.Set(key, val2, time.Hour) + gtest.Nil(t, err) + var r3 int + err = cm.Get(key, &r3) + gtest.Nil(t, err) + gtest.Equal(t, val2, r3) + + n, err := cm.Del(key) + gtest.Nil(t, err) + gtest.Equal(t, int64(1), n) +} diff --git a/gcache/readme.adoc b/gcache/readme.adoc index 812ff77..e0215cd 100644 --- a/gcache/readme.adoc +++ b/gcache/readme.adoc @@ -15,12 +15,19 @@ :imagesdir: ./img -**注:** 暂时直接使用 `go-resdis/cache` +== 实现 +已于 2023-06-21 实现。 + +可以基于 `redis` 进行一些基本使用。 + + + +== 设计 从使用倒推设计。 -== 场景1 +=== 场景1 自己管理 `key`: @@ -38,7 +45,7 @@ return data <1> `get` 值为 `false` 表示没有缓存或缓存已过期 <2> 7200 为缓存有效期(单位为秒),若指定为 0 表示不过期。 -== 场景2 +=== 场景2 程序自动管理 `key`: