From ef85d7d1b4723f354e46d81a04d2ae9fa4e2ef25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BD=AD=E4=B8=9A=E6=98=8C?= Date: Tue, 16 May 2023 15:56:57 +0800 Subject: [PATCH] =?UTF-8?q?feat(freecache):=20=E6=96=B0=E5=A2=9E=E5=8D=95?= =?UTF-8?q?=E7=8B=AC=E8=8E=B7=E5=8F=96=E5=92=8C=E8=AE=BE=E7=BD=AE=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E7=BC=93=E5=AD=98=E7=9A=84=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cache/xfreecache/v2/cache.go | 54 ++++++++++++++++++++++++--- pkg/cache/xfreecache/v2/cache_test.go | 40 ++++++++++++++++++++ website/docs/jupiter/4.9freecache.md | 26 +++++++++++++ 3 files changed, 114 insertions(+), 6 deletions(-) diff --git a/pkg/cache/xfreecache/v2/cache.go b/pkg/cache/xfreecache/v2/cache.go index c777c3c9ff..8fc8749116 100644 --- a/pkg/cache/xfreecache/v2/cache.go +++ b/pkg/cache/xfreecache/v2/cache.go @@ -28,15 +28,50 @@ func (c *cache[K, V]) GetAndSetCacheData(key string, id K, fn func() (V, error)) return } +// GetCacheValue 获取缓存数据 +func (c *cache[K, V]) GetCacheValue(key string, id K) (value V) { + resMap, _ := c.getCacheMap(key, []K{id}) + value = resMap[id] + return +} + +// SetCacheValue 设置缓存数据 +func (c *cache[K, V]) SetCacheValue(key string, id K, fn func() (V, error)) (err error) { + err = c.setCacheMap(key, []K{id}, func([]K) (map[K]V, error) { + innerVal, innerErr := fn() + return map[K]V{id: innerVal}, innerErr + }, nil) + return +} + // GetAndSetCacheMap 获取缓存后数据 map形式 func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K]V, error)) (v map[K]V, err error) { - args := []zap.Field{zap.Any("key", key), zap.Any("ids", ids)} + // 获取缓存数据 + v, idsNone := c.getCacheMap(key, ids) + + // 设置缓存数据 + err = c.setCacheMap(key, idsNone, fn, v) + return +} + +// GetCacheMap 获取缓存数据 map形式 +func (c *cache[K, V]) GetCacheMap(key string, ids []K) (v map[K]V) { + v, _ = c.getCacheMap(key, ids) + return +} +// SetCacheMap 设置缓存数据 map形式 +func (c *cache[K, V]) SetCacheMap(key string, ids []K, fn func([]K) (map[K]V, error)) (err error) { + err = c.setCacheMap(key, ids, fn, nil) + return +} + +func (c *cache[K, V]) getCacheMap(key string, ids []K) (v map[K]V, idsNone []K) { v = make(map[K]V) + idsNone = make([]K, 0, len(ids)) // id去重 ids = lo.Uniq(ids) - idsNone := make([]K, 0, len(ids)) for _, id := range ids { cacheKey := c.getKey(key, id) resT, innerErr := c.GetCacheData(cacheKey) @@ -45,7 +80,7 @@ func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K // 反序列化 value, innerErr = unmarshal[V](resT) if innerErr != nil { - xlog.Jupiter().Error("cache unmarshalWithPool", zap.String("key", key), zap.Error(err)) + xlog.Jupiter().Error("cache unmarshalWithPool", zap.String("key", key), zap.Error(innerErr)) } else { v[id] = value } @@ -54,6 +89,11 @@ func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K idsNone = append(idsNone, id) } } + return +} + +func (c *cache[K, V]) setCacheMap(key string, idsNone []K, fn func([]K) (map[K]V, error), v map[K]V) (err error) { + args := []zap.Field{zap.Any("key", key), zap.Any("ids", idsNone)} if len(idsNone) == 0 { return @@ -67,8 +107,10 @@ func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K } // 填入返回中 - for k, value := range resMap { - v[k] = value + if v != nil { + for k, value := range resMap { + v[k] = value + } } // 写入缓存 @@ -78,7 +120,7 @@ func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K data []byte ) - if val, ok := v[id]; ok { + if val, ok := resMap[id]; ok { cacheData = val } // 序列化 diff --git a/pkg/cache/xfreecache/v2/cache_test.go b/pkg/cache/xfreecache/v2/cache_test.go index ce3491f4db..5760dc11da 100644 --- a/pkg/cache/xfreecache/v2/cache_test.go +++ b/pkg/cache/xfreecache/v2/cache_test.go @@ -74,6 +74,26 @@ func Test_cache_GetAndSetCacheData(t *testing.T) { assert.Equalf(t, tt.stu, result, "GetAndSetCacheData(%v) cache value error", key) } assert.Equalf(t, missCount, 3, "GetAndSetCacheData miss count error") + + missCount = 0 + for _, tt := range tests { + key := fmt.Sprintf("%d-%s-new", tt.stu.Age, tt.stu.Name) + + result := oneCache.GetCacheValue(key, tt.stu.Name) + fmt.Println(result) + if result == (Student{}) { + missCount++ + fmt.Println("local cache miss hit") + } else { + assert.Equalf(t, tt.stu, result, "split GetAndSetCacheData(%v) cache value error", key) + } + + err := oneCache.SetCacheValue(key, tt.stu.Name, func() (Student, error) { + return tt.stu, nil + }) + assert.Emptyf(t, err, "split GetAndSetCacheData err not nil") + } + assert.Equalf(t, missCount, 3, "split GetAndSetCacheData miss count error") } func Test_cache_GetAndSetCacheData_proto(t *testing.T) { @@ -134,6 +154,26 @@ func Test_cache_GetAndSetCacheData_proto(t *testing.T) { assert.Equalf(t, tt.stu.GetName(), result.GetName(), "GetAndSetCacheData(%v) cache value error", key) } assert.Equalf(t, missCount, 4, "GetAndSetCacheData miss count error") + + missCount = 0 + for _, tt := range tests { + key := tt.stu.GetName() + "-new" + + result := oneCache.GetCacheValue(key, tt.stu.GetName()) + fmt.Println(result) + if result == nil { + missCount++ + fmt.Println("local cache miss hit") + } else { + assert.Equalf(t, tt.stu.GetName(), result.GetName(), "split GetAndSetCacheData(%v) cache value error", key) + } + + err := oneCache.SetCacheValue(key, tt.stu.GetName(), func() (*helloworldv1.SayHiRequest, error) { + return tt.stu, nil + }) + assert.Emptyf(t, err, "split GetAndSetCacheData err not nil") + } + assert.Equalf(t, missCount, 5, "split GetAndSetCacheData miss count error") } func Test_cache_GetAndSetCacheMap(t *testing.T) { diff --git a/website/docs/jupiter/4.9freecache.md b/website/docs/jupiter/4.9freecache.md index 76109fb4dc..7d797116ed 100644 --- a/website/docs/jupiter/4.9freecache.md +++ b/website/docs/jupiter/4.9freecache.md @@ -65,6 +65,19 @@ func NewInstance() *Instance { // err fn返回的错误以及其他报错 func (c *cache[K, V]) GetAndSetCacheData(key string, id K, fn func() (V, error)) (value V, err error) +// GetCacheValue 获取缓存数据 +// key 缓存key +// id 索引(无作用,会组装到key里面) +// value +func (c *cache[K, V]) GetCacheValue(key string, id K) (value V) + +// SetCacheValue 设置缓存数据 +// key 缓存key +// id 索引(无作用,会组装到key里面) +// fn 获取返回数据需要执行的方法 +// err fn返回的错误以及其他报错 +func (c *cache[K, V]) SetCacheValue(key string, id K, fn func() (V, error)) (err error) + // GetAndSetCacheMap 获取缓存后数据 map形式 【推荐使用】 // key 缓存key // ids 返回map中的key集合 @@ -73,6 +86,19 @@ func (c *cache[K, V]) GetAndSetCacheData(key string, id K, fn func() (V, error)) // err fn返回的错误以及其他报错 func (c *cache[K, V]) GetAndSetCacheMap(key string, ids []K, fn func([]K) (map[K]V, error)) (v map[K]V, err error) +// GetCacheMap 获取缓存数据 map形式 +// key 缓存key +// ids 返回map中的key集合 +// value +func (c *cache[K, V]) GetCacheMap(key string, ids []K) (v map[K]V) + +// SetCacheMap 设置缓存数据 map形式 +// key 缓存key +// ids 返回map中的key集合 +// fn 获取返回数据需要执行的方法 +// err fn返回的错误以及其他报错 +func (c *cache[K, V]) SetCacheMap(key string, ids []K, fn func([]K) (map[K]V, error)) (err error) + // SetCacheData 设置本地缓存 // key 缓存key // data 缓存value,传入序列化后的字节数组