From 43da4f56daf5b0825b8959bbf477d5777fdcd46d Mon Sep 17 00:00:00 2001 From: Aleksandr Soloshenko Date: Thu, 11 Sep 2025 11:41:40 +0700 Subject: [PATCH] [cache] add app-wide prefix --- internal/sms-gateway/cache/factory.go | 6 +++++- pkg/cache/memory.go | 7 ++++--- pkg/cache/memory_edge_test.go | 2 +- pkg/cache/memory_profile_test.go | 4 ++-- pkg/cache/redis.go | 25 +++++++++++++++++++++---- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/internal/sms-gateway/cache/factory.go b/internal/sms-gateway/cache/factory.go index 2f0a536..0c088c1 100644 --- a/internal/sms-gateway/cache/factory.go +++ b/internal/sms-gateway/cache/factory.go @@ -8,6 +8,10 @@ import ( "github.com/android-sms-gateway/server/pkg/cache" ) +const ( + keyPrefix = "sms-gateway:" +) + type Cache = cache.Cache type Factory interface { @@ -52,5 +56,5 @@ func NewFactory(config Config) (Factory, error) { // New implements Factory. func (f *factory) New(name string) (cache.Cache, error) { - return f.new(name) + return f.new(keyPrefix + name) } diff --git a/pkg/cache/memory.go b/pkg/cache/memory.go index 612227b..6a1a18c 100644 --- a/pkg/cache/memory.go +++ b/pkg/cache/memory.go @@ -110,12 +110,13 @@ func (m *memoryCache) SetOrFail(_ context.Context, key string, value string, opt m.mux.Lock() defer m.mux.Unlock() - if _, ok := m.items[key]; ok { - return ErrKeyExists + if item, ok := m.items[key]; ok { + if !item.isExpired(time.Now()) { + return ErrKeyExists + } } m.items[key] = m.newItem(value, opts...) - return nil } diff --git a/pkg/cache/memory_edge_test.go b/pkg/cache/memory_edge_test.go index 1134f6a..8fb9cba 100644 --- a/pkg/cache/memory_edge_test.go +++ b/pkg/cache/memory_edge_test.go @@ -241,7 +241,7 @@ func TestMemoryCache_RapidOperations(t *testing.T) { } else { key := "rapid-key-" + strconv.Itoa(i-1) _, err := c.Get(ctx, key) - if err != nil && err != cache.ErrKeyNotFound { + if err != nil { t.Errorf("Get failed: %v", err) } } diff --git a/pkg/cache/memory_profile_test.go b/pkg/cache/memory_profile_test.go index 5214ac4..c7c0493 100644 --- a/pkg/cache/memory_profile_test.go +++ b/pkg/cache/memory_profile_test.go @@ -189,10 +189,10 @@ func TestMemoryCache_GCStress(t *testing.T) { runtime.GC() // Verify cache operations still work - for j := 0; j < 100; j++ { + for j := range 100 { key := "gc-key-" + strconv.Itoa(j) _, err := c.Get(ctx, key) - if err != nil && err != cache.ErrKeyNotFound { + if err != nil { t.Errorf("Get failed during GC stress test: %v", err) } } diff --git a/pkg/cache/redis.go b/pkg/cache/redis.go index 07d62ee..a692d71 100644 --- a/pkg/cache/redis.go +++ b/pkg/cache/redis.go @@ -21,6 +21,16 @@ if value then else return false end +` + + hgetallAndDeleteScript = ` +local items = redis.call('HGETALL', KEYS[1]) +if #items > 0 then + for i = 1, #items, 2 do + redis.call('HDEL', KEYS[1], items[i]) + end +end +return items ` ) @@ -62,17 +72,24 @@ func (r *redisCache) Delete(ctx context.Context, key string) error { // Drain implements Cache. func (r *redisCache) Drain(ctx context.Context) (map[string]string, error) { - items, err := r.client.HGetAll(ctx, r.key).Result() + res, err := r.client.Eval(ctx, hgetallAndDeleteScript, []string{r.key}).Result() if err != nil { return nil, fmt.Errorf("can't drain cache: %w", err) } - if err := r.client.Del(ctx, r.key).Err(); err != nil { - return nil, fmt.Errorf("can't cleanup cache: %w", err) + arr, ok := res.([]any) + if !ok || len(arr) == 0 { + return map[string]string{}, nil } - return items, nil + out := make(map[string]string, len(arr)/2) + for i := 0; i < len(arr); i += 2 { + f, _ := arr[i].(string) + v, _ := arr[i+1].(string) + out[f] = v + } + return out, nil } // Get implements Cache.