From 39e98537fd342dac1bcb1f6f118c97d70711e85e Mon Sep 17 00:00:00 2001 From: Vincent Boutour Date: Fri, 11 Aug 2023 23:49:16 +0200 Subject: [PATCH] feat(cache): Setting optional extend on hit Signed-off-by: Vincent Boutour --- pkg/cache/cache.go | 13 +++++++++++-- pkg/cache/cache_test.go | 5 +++++ pkg/cache/list.go | 10 ++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index dd2ddcbd..1135a0e6 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -43,6 +43,7 @@ type App[K comparable, V any] struct { onMissMany fetchMany[K, V] ttl time.Duration concurrency int + extendOnHit bool } func New[K comparable, V any](client RedisClient, toKey func(K) string, onMiss fetch[K, V], ttl time.Duration, concurrency int, tracer trace.Tracer) *App[K, V] { @@ -78,6 +79,12 @@ func (a *App[K, V]) WithRead(client RedisClient) *App[K, V] { return a } +func (a *App[K, V]) WithExtendOnHit() *App[K, V] { + a.extendOnHit = true + + return a +} + func getClient(client RedisClient) RedisClient { if !model.IsNil(client) && client.Enabled() { return client @@ -110,7 +117,9 @@ func (a *App[K, V]) Get(ctx context.Context, id K) (V, error) { } else if value, ok, err := a.decode([]byte(content)); err != nil { logUnmarshallError(ctx, key, err) } else if ok { - a.extendTTL(ctx, key) + if a.extendOnHit { + a.extendTTL(ctx, key) + } return value, nil } @@ -166,7 +175,7 @@ func (a *App[K, V]) decode(content []byte) (value V, ok bool, err error) { } func (a *App[K, V]) extendTTL(ctx context.Context, keys ...string) { - if a.write == nil { + if a.write == nil || len(keys) == 0 { return } diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go index 96288af0..f04e3530 100644 --- a/pkg/cache/cache_test.go +++ b/pkg/cache/cache_test.go @@ -131,6 +131,8 @@ func TestGet(t *testing.T) { case "cached": mockRedisClient.EXPECT().Load(gomock.Any(), gomock.Any()).Return([]byte(`{"id":8000}`), nil) mockRedisClient.EXPECT().Expire(gomock.Any(), testCase.args.duration, gomock.Any()).Return(nil) + case "cached no extend": + mockRedisClient.EXPECT().Load(gomock.Any(), gomock.Any()).Return([]byte(`{"id":8000}`), nil) case "store error": mockRedisClient.EXPECT().Load(gomock.Any(), gomock.Any()).Return(nil, nil) mockRedisClient.EXPECT().Store(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("store error")) @@ -147,6 +149,9 @@ func TestGet(t *testing.T) { } instance := New(mockRedisClient, strconv.Itoa, testCase.args.onMiss, testCase.args.duration, -1, nil) + if intention == "cached" { + instance = instance.WithExtendOnHit() + } got, gotErr := instance.Get(context.Background(), testCase.args.key) diff --git a/pkg/cache/list.go b/pkg/cache/list.go index 4cc8d3eb..165591ea 100644 --- a/pkg/cache/list.go +++ b/pkg/cache/list.go @@ -95,7 +95,10 @@ func (a App[K, V]) handleListSingle(ctx context.Context, onMissError func(K, err value, ok, err := a.decode([]byte(values[index])) if ok { output[index] = value - extendKeys = append(extendKeys, keys[index]) + + if a.extendOnHit { + extendKeys = append(extendKeys, keys[index]) + } return nil } @@ -127,7 +130,10 @@ func (a App[K, V]) handleListMany(ctx context.Context, items []K, keys, values [ for index, item := range items { if value, ok, err := a.decode([]byte(values[index])); ok { output[index] = value - extendKeys = append(extendKeys, keys[index]) + + if a.extendOnHit { + extendKeys = append(extendKeys, keys[index]) + } continue } else if err != nil {