From a7f76bf3ecad78bb63e3d6b3ea6da59b3ed5cb60 Mon Sep 17 00:00:00 2001 From: Ratko Rudic Date: Mon, 28 Nov 2022 09:38:08 +0100 Subject: [PATCH] Adds ValueOnly() function that returns cached value but doesn't update it's keepAlive. CacheTable.ValueOnly() works identically to CacheTable.Value() function, but doesn't update it's CacheItem.keepAlive value. Can be used to retrieve cached value without touching it or changing any of it's properties. --- README.md | 8 ++++++++ cache_test.go | 13 +++++++++++++ cachetable.go | 16 ++++++++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07f495e..7977f99 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,14 @@ func main() { fmt.Println("Error retrieving value from cache:", err) } + // You can also retrieve Value without affecting it's keep alive + res, err := cache.ValueOnly("someKey") + if err == nil { + fmt.Println("Found value in cache:", res.Data().(*myStruct).text) + } else { + fmt.Println("Error retrieving value from cache:", err) + } + // Wait for the item to expire in cache. time.Sleep(6 * time.Second) res, err = cache.Value("someKey") diff --git a/cache_test.go b/cache_test.go index e195e93..a590e2b 100644 --- a/cache_test.go +++ b/cache_test.go @@ -59,6 +59,7 @@ func TestCacheExpire(t *testing.T) { table.Add(k+"_1", 250*time.Millisecond, v+"_1") table.Add(k+"_2", 200*time.Millisecond, v+"_2") + table.Add(k+"_3", 200*time.Millisecond, v+"_3") time.Sleep(100 * time.Millisecond) @@ -68,6 +69,12 @@ func TestCacheExpire(t *testing.T) { t.Error("Error retrieving value from cache:", err) } + // check key `3`: valueOnly does not extend keep alive + _, err = table.ValueOnly(k + "_3") + if err != nil { + t.Error("Error retrieving value from cache:", err) + } + time.Sleep(150 * time.Millisecond) // check key `1` again, it should still be alive since we just accessed it @@ -81,6 +88,12 @@ func TestCacheExpire(t *testing.T) { if err == nil { t.Error("Found key which should have been expired by now") } + + // check key `3`, it should have been removed by now + _, err = table.Value(k + "_3") + if err == nil { + t.Error("Found key which should have been expired by now") + } } func TestExists(t *testing.T) { diff --git a/cachetable.go b/cachetable.go index 1fa75ad..0fdf443 100644 --- a/cachetable.go +++ b/cachetable.go @@ -76,7 +76,7 @@ func (table *CacheTable) SetAddedItemCallback(f func(*CacheItem)) { table.addedItem = append(table.addedItem, f) } -//AddAddedItemCallback appends a new callback to the addedItem queue +// AddAddedItemCallback appends a new callback to the addedItem queue func (table *CacheTable) AddAddedItemCallback(f func(*CacheItem)) { table.Lock() defer table.Unlock() @@ -278,6 +278,16 @@ func (table *CacheTable) NotFoundAdd(key interface{}, lifeSpan time.Duration, da // Value returns an item from the cache and marks it to be kept alive. You can // pass additional arguments to your DataLoader callback function. func (table *CacheTable) Value(key interface{}, args ...interface{}) (*CacheItem, error) { + return table.valueInternal(key, true, args) +} + +// ValueOnly returns an item from the cache and does not mark it to be kept alive. You can +// pass additional arguments to your DataLoader callback function. +func (table *CacheTable) ValueOnly(key interface{}, args ...interface{}) (*CacheItem, error) { + return table.valueInternal(key, false, args) +} + +func (table *CacheTable) valueInternal(key interface{}, updateKeepAlive bool, args ...interface{}) (*CacheItem, error) { table.RLock() r, ok := table.items[key] loadData := table.loadData @@ -285,7 +295,9 @@ func (table *CacheTable) Value(key interface{}, args ...interface{}) (*CacheItem if ok { // Update access counter and timestamp. - r.KeepAlive() + if updateKeepAlive { + r.KeepAlive() + } return r, nil }