From 5298a2cabf4673e8820702d51540e102d64dd401 Mon Sep 17 00:00:00 2001 From: bryanqiu Date: Thu, 7 Sep 2023 11:52:20 +0800 Subject: [PATCH] cocurrent fix --- cache.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/cache.go b/cache.go index 38a5710..9f4e0ba 100644 --- a/cache.go +++ b/cache.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "reflect" + "sync" "time" "github.com/gomodule/redigo/redis" @@ -69,7 +70,7 @@ func NewCache[T any](getter Getter[T], cfg Config) Cacher[T] { if cfg.UseLocalCache { c.localCache = new(localCacher[T]) c.localCache.cacher = c - c.localCache.cacheItems = map[string]*cacheItem[T]{} + c.localCache.cacheItems = sync.Map{} //map[string]*cacheItem[T]{} c.localCache.cacheDuration = time.Duration(cfg.LocalCacheLifetimeSecond) * time.Second if c.localCache.cacheDuration.Nanoseconds() == 0 { c.localCache.cacheDuration = 60 * time.Second @@ -159,9 +160,9 @@ type cacheItem[T any] struct { } type localCacher[T any] struct { - cacher *cacher[T] - cacheItems map[string]*cacheItem[T] - cacheDuration time.Duration + cacher *cacher[T] // parents cacher pointer + cacheItems sync.Map // map[string]*cacheItem[T] + cacheDuration time.Duration // cache alive duration } type redisCacher[T any] struct { @@ -174,9 +175,11 @@ type redisCacher[T any] struct { func (c *localCacher[T]) GetFromCache(id string, options ...Option) (t *T, err error) { // Step 1. get from map - var a, ok = c.cacheItems[id] - if !ok { + var a *cacheItem[T] = nil + if aa, ok := c.cacheItems.Load(id); !ok { return nil, ErrNotFound + } else if a, ok = aa.(*cacheItem[T]); !ok { + panic("unreachable code, inner item type must be '*cacheItem[T]'") } // Step 2. check is expired or not @@ -189,8 +192,7 @@ func (c *localCacher[T]) GetFromCache(id string, options ...Option) (t *T, err e err = ErrExpired } else { log.Infof("cache(%s) is in local cache but expired, we delete it", id) - //TODO: cocurrent - delete(c.cacheItems, id) + c.cacheItems.Delete(id) return nil, ErrNotFound } } @@ -206,7 +208,7 @@ func (c *localCacher[T]) GetFromCache(id string, options ...Option) (t *T, err e if err == ErrExpired { return a.Data, ErrExpired } else if err != nil { - panic("unreachable code") + panic("unreachable code: only ErrExpired error valid when data exist") } return a.Data, nil } @@ -219,7 +221,7 @@ func (c *localCacher[T]) SetIntoCache(id string, t *T, options ...Option) (err e } else { newitem.CreateTime = time.Now() } - c.cacheItems[id] = newitem + c.cacheItems.Store(id, newitem) return nil }