Added function GetNotExpiredItems to get all not expired items in a threadsafe manner
This commit is contained in:
parent
1881a9bccb
commit
c193f8a44d
16
cache.go
16
cache.go
|
@ -1009,6 +1009,22 @@ func (c *cache) Items() map[string]Item {
|
||||||
return c.items
|
return c.items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns all not expired items in the cache. This method is save to use with
|
||||||
|
// an active janitor since it copies the underlying map. Therefore method is
|
||||||
|
// costly in terms of time and memory. You can read while using this method but
|
||||||
|
// not write. Use with caution.
|
||||||
|
func (c *cache) GetNotExpiredItems() map[string]Item {
|
||||||
|
retMap := make(map[string]Item, c.ItemCount())
|
||||||
|
c.mu.RLock()
|
||||||
|
for key, item := range c.items{
|
||||||
|
if !item.Expired() {
|
||||||
|
retMap[key] = item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.mu.RUnlock()
|
||||||
|
return retMap
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the number of items in the cache. This may include items that have
|
// Returns the number of items in the cache. This may include items that have
|
||||||
// expired, but have not yet been cleaned up. Equivalent to len(c.Items()).
|
// expired, but have not yet been cleaned up. Equivalent to len(c.Items()).
|
||||||
func (c *cache) ItemCount() int {
|
func (c *cache) ItemCount() int {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestStruct struct {
|
type TestStruct struct {
|
||||||
|
@ -1247,6 +1248,29 @@ func TestOnEvicted(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCacheGetAllNotExpiredItems(t *testing.T) {
|
||||||
|
tc := New(time.Minute*1, 0)
|
||||||
|
tc.Set("a", "a", DefaultExpiration)
|
||||||
|
tc.Set("b", "b", DefaultExpiration)
|
||||||
|
tc.Set("c", "c", time.Millisecond*1)
|
||||||
|
time.Sleep(time.Millisecond*2)
|
||||||
|
allNotExpiredItems := tc.GetNotExpiredItems()
|
||||||
|
if len(allNotExpiredItems) != 2 {
|
||||||
|
t.Error("There are more or less items in the result than the two unexpired.")
|
||||||
|
}
|
||||||
|
for _, key := range []string{"a", "b"} {
|
||||||
|
if _, ok := tc.Get(key); !ok{
|
||||||
|
t.Error("Could not find unexpired item %s", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := tc.Get("c"); ok {
|
||||||
|
t.Error("Found expired item c.")
|
||||||
|
}
|
||||||
|
if &allNotExpiredItems == &tc.cache.items {
|
||||||
|
t.Error("Returned map is equal to internal map.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCacheSerialization(t *testing.T) {
|
func TestCacheSerialization(t *testing.T) {
|
||||||
tc := New(DefaultExpiration, 0)
|
tc := New(DefaultExpiration, 0)
|
||||||
testFillAndSerialize(t, tc)
|
testFillAndSerialize(t, tc)
|
||||||
|
@ -1676,3 +1700,18 @@ func BenchmarkDeleteExpiredLoop(b *testing.B) {
|
||||||
tc.DeleteExpired()
|
tc.DeleteExpired()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkGetAllNotExpiredItems(b *testing.B) {
|
||||||
|
for i:= 0; i < 20; i++ {
|
||||||
|
b.Run(fmt.Sprintf("BenchmarkGetAllNotExpiredItemsWith %d000 Items", i), func(b *testing.B){
|
||||||
|
tc := New(20*time.Minute, 0)
|
||||||
|
for j:= 0; j < i*1000; j++{
|
||||||
|
tc.Set(strconv.Itoa(i), "bar", DefaultExpiration)
|
||||||
|
}
|
||||||
|
b.ResetTimer()
|
||||||
|
for j:= 0; j < b.N; j++{
|
||||||
|
tc.GetNotExpiredItems()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue