From 253b27a99fee1049e4b5c5dc7bebe2fde0119ba7 Mon Sep 17 00:00:00 2001 From: Francesco Cosentino Date: Sat, 21 Jan 2023 13:54:54 +0100 Subject: [PATCH] added method GetWithInfo --- hypercache.go | 21 +++++++++++++++++++++ middleware/logging.go | 10 ++++++++++ middleware/stats.go | 10 ++++++++++ service.go | 2 ++ 4 files changed, 43 insertions(+) diff --git a/hypercache.go b/hypercache.go index 8448a0d..4d19e42 100644 --- a/hypercache.go +++ b/hypercache.go @@ -392,6 +392,27 @@ func (hyperCache *HyperCache[T]) Get(key string) (value any, ok bool) { return item.Value, true } +func (hyperCache *HyperCache[T]) GetWithInfo(key string) (*models.Item, bool) { + item, ok := hyperCache.backend.Get(key) + // Check if the item has expired if it exists, if so, trigger the expiration loop + if !ok { + return nil, false + } + + // Check if the item has expired, if so, trigger the expiration loop + if item.Expired() { + go func() { + models.ItemPool.Put(item) + hyperCache.expirationTriggerCh <- true + }() + return nil, false + } + + // Update the last access time and access count + item.Touch() + return item, true +} + // GetOrSet retrieves the item with the given key. If the item is not found, it adds the item to the cache with the given value and expiration duration. // If the capacity of the cache is reached, leverage the eviction algorithm. func (hyperCache *HyperCache[T]) GetOrSet(key string, value any, expiration time.Duration) (any, error) { diff --git a/middleware/logging.go b/middleware/logging.go index f5b1924..471cefe 100644 --- a/middleware/logging.go +++ b/middleware/logging.go @@ -57,6 +57,16 @@ func (mw LoggingMiddleware) GetOrSet(key string, value any, expiration time.Dura return mw.next.GetOrSet(key, value, expiration) } +// GetWithInfo logs the time it takes to execute the next middleware. +func (mw LoggingMiddleware) GetWithInfo(key string) (item *models.Item, ok bool) { + defer func(begin time.Time) { + mw.logger.Printf("method GetWithInfo took: %s", time.Since(begin)) + }(time.Now()) + + mw.logger.Printf("GetWithInfo method invoked with key: %s", key) + return mw.next.GetWithInfo(key) +} + // GetMultiple logs the time it takes to execute the next middleware. func (mw LoggingMiddleware) GetMultiple(keys ...string) (result map[string]any, failed map[string]error) { defer func(begin time.Time) { diff --git a/middleware/stats.go b/middleware/stats.go index f6334a3..4d429b6 100644 --- a/middleware/stats.go +++ b/middleware/stats.go @@ -50,6 +50,16 @@ func (mw StatsCollectorMiddleware) GetOrSet(key string, value any, expiration ti return mw.next.GetOrSet(key, value, expiration) } +// GetWithInfo collects stats for the GetWithInfo method. +func (mw StatsCollectorMiddleware) GetWithInfo(key string) (*models.Item, bool) { + start := time.Now() + defer func() { + mw.statsCollector.Timing("hypercache_get_with_info_duration", time.Since(start).Nanoseconds()) + mw.statsCollector.Incr("hypercache_get_with_info_count", 1) + }() + return mw.next.GetWithInfo(key) +} + // GetMultiple collects stats for the GetMultiple method. func (mw StatsCollectorMiddleware) GetMultiple(keys ...string) (result map[string]any, failed map[string]error) { start := time.Now() diff --git a/service.go b/service.go index 9d8ea44..e915103 100644 --- a/service.go +++ b/service.go @@ -16,6 +16,8 @@ type Service interface { Set(key string, value any, expiration time.Duration) error // GetOrSet retrieves a value from the cache using the key, if the key does not exist, it will set the value using the key and expiration duration GetOrSet(key string, value any, expiration time.Duration) (any, error) + // GetWithInfo fetches from the cache using the key, and returns the `models.Item` and a boolean indicating if the key exists + GetWithInfo(key string) (*models.Item, bool) // GetMultiple retrieves a list of values from the cache using the keys GetMultiple(keys ...string) (result map[string]any, failed map[string]error) // List returns a list of all items in the cache