From 98ae47f1b922e4fe57c97b8e0eac859e8b972cf5 Mon Sep 17 00:00:00 2001 From: Ben Perry Date: Tue, 28 May 2024 09:39:07 -0500 Subject: [PATCH] Enable iteration of key/val pairs in expirable LRU --- expirable/expirable_lru.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/expirable/expirable_lru.go b/expirable/expirable_lru.go index 8e70082..c26b6a9 100644 --- a/expirable/expirable_lru.go +++ b/expirable/expirable_lru.go @@ -251,6 +251,16 @@ func (c *LRU[K, V]) Values() []V { return values } +// Range calls a function on key/value pairs in the cache, from oldest to newest, +// until the provided callback returns true. Expired entries are filtered out. +func (c *LRU[K, V]) Range(callback func(key K, value V) (done bool)) { + for _, ent := range c.entries() { + if callback(ent.Key, ent.Value) { + return + } + } +} + // Len returns the number of items in the cache. func (c *LRU[K, V]) Len() int { c.mu.Lock() @@ -340,7 +350,23 @@ func (c *LRU[K, V]) removeFromBucket(e *internal.Entry[K, V]) { delete(c.buckets[e.ExpireBucket].entries, e.Key) } +// entries returns a slice of the current internal entries in the cache +func (c *LRU[K, V]) entries() []*internal.Entry[K, V] { + c.mu.Lock() + defer c.mu.Unlock() + + entries := make([]*internal.Entry[K, V], 0, len(c.items)) + now := time.Now() + for ent := c.evictList.Back(); ent != nil; ent = ent.PrevEntry() { + if now.After(ent.ExpiresAt) { + continue + } + entries = append(entries, ent) + } + return entries +} + // Cap returns the capacity of the cache func (c *LRU[K, V]) Cap() int { return c.size -} \ No newline at end of file +}