From 9376467526c6751b234027b48bc500a05cc8a429 Mon Sep 17 00:00:00 2001 From: ensiouel <ensiouel@gmail.com> Date: Thu, 14 Dec 2023 15:10:38 +0300 Subject: [PATCH] =?UTF-8?q?Cache=20=D0=B1=D1=8B=D0=BB=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B5=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=B2?= =?UTF-8?q?=20MemoryCache,=20=D1=81=D0=B0=D0=BC=20Cache=20=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=BB=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9?= =?UTF-8?q?=D1=81=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/cache/cache.go | 89 ++------------------------------------ pkg/cache/memory_cache.go | 90 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 85 deletions(-) create mode 100644 pkg/cache/memory_cache.go diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index c71b426f..e8feb4ce 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -1,88 +1,7 @@ package cache -import ( - "fmt" - "time" - - "git.perx.ru/perxis/perxis-go/pkg/service" - lru "github.com/hashicorp/golang-lru/v2" - "go.uber.org/zap" -) - -const ( - defaultCacheSize = 1000 - defaultTTL = 30 * time.Second -) - -type Cache struct { - cache *lru.Cache[interface{}, interface{}] - ttl time.Duration - logger *zap.Logger -} - -type item struct { - value interface{} - expiredAt time.Time -} - -func NewCache(size int, ttl time.Duration, opts ...interface{}) *Cache { - if size == 0 { - size = defaultCacheSize - } - if ttl == 0 { - ttl = defaultTTL - } - c, err := lru.New[interface{}, interface{}](size) - if err != nil { - panic(err) - } - ch := &Cache{ - cache: c, - ttl: ttl, - logger: zap.NewNop(), - } - - for _, o := range opts { - switch p := o.(type) { - case *zap.Logger: - ch.logger = p - } - } - - ch.logger = ch.logger.Named("Cache") - - return ch -} - -func (c *Cache) Set(key, value interface{}) (err error) { - c.cache.Add(key, &item{value: value, expiredAt: time.Now().Add(c.ttl)}) - c.logger.Debug("Set", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", value))) - return nil -} - -func (c *Cache) Get(key interface{}) (value interface{}, err error) { - val, ok := c.cache.Get(key) - if ok { - v := val.(*item) - if v.expiredAt.Before(time.Now()) { - _ = c.Remove(key) - c.logger.Debug("Expired", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", v.value))) - return nil, service.ErrNotFound - } - c.logger.Debug("Hit", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", v.value))) - return v.value, nil - } - c.logger.Debug("Miss", zap.String("key", fmt.Sprintf("%v", key))) - return nil, service.ErrNotFound -} - -func (c *Cache) Remove(key interface{}) (err error) { - present := c.cache.Remove(key) - c.logger.Debug("Remove", zap.String("key", fmt.Sprintf("%v", key))) - - if !present { - err = service.ErrNotFound - } - - return +type Cache interface { + Set(key, value any) error + Get(key any) (any, error) + Remove(key any) error } diff --git a/pkg/cache/memory_cache.go b/pkg/cache/memory_cache.go new file mode 100644 index 00000000..12b9b558 --- /dev/null +++ b/pkg/cache/memory_cache.go @@ -0,0 +1,90 @@ +package cache + +import ( + "fmt" + "time" + + "git.perx.ru/perxis/perxis-go/pkg/service" + lru "github.com/hashicorp/golang-lru/v2" + "go.uber.org/zap" +) + +const ( + defaultCacheSize = 1000 + defaultTTL = 30 * time.Second +) + +var _ Cache = &MemoryCache{} + +type MemoryCache struct { + cache *lru.Cache[interface{}, interface{}] + ttl time.Duration + logger *zap.Logger +} + +type item struct { + value interface{} + expiredAt time.Time +} + +func NewMemoryCache(size int, ttl time.Duration, opts ...interface{}) *MemoryCache { + if size == 0 { + size = defaultCacheSize + } + if ttl == 0 { + ttl = defaultTTL + } + c, err := lru.New[interface{}, interface{}](size) + if err != nil { + panic(err) + } + ch := &MemoryCache{ + cache: c, + ttl: ttl, + logger: zap.NewNop(), + } + + for _, o := range opts { + switch p := o.(type) { + case *zap.Logger: + ch.logger = p + } + } + + ch.logger = ch.logger.Named("Cache") + + return ch +} + +func (c *MemoryCache) Set(key, value interface{}) (err error) { + c.cache.Add(key, &item{value: value, expiredAt: time.Now().Add(c.ttl)}) + c.logger.Debug("Set", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", value))) + return nil +} + +func (c *MemoryCache) Get(key interface{}) (value interface{}, err error) { + val, ok := c.cache.Get(key) + if ok { + v := val.(*item) + if v.expiredAt.Before(time.Now()) { + _ = c.Remove(key) + c.logger.Debug("Expired", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", v.value))) + return nil, service.ErrNotFound + } + c.logger.Debug("Hit", zap.String("key", fmt.Sprintf("%v", key)), zap.String("ptr", fmt.Sprintf("%p", v.value))) + return v.value, nil + } + c.logger.Debug("Miss", zap.String("key", fmt.Sprintf("%v", key))) + return nil, service.ErrNotFound +} + +func (c *MemoryCache) Remove(key interface{}) (err error) { + present := c.cache.Remove(key) + c.logger.Debug("Remove", zap.String("key", fmt.Sprintf("%v", key))) + + if !present { + err = service.ErrNotFound + } + + return +} -- GitLab