Delete expired items before setting
Check if an item exists and it has expired before setting so that onEvicted is actually called. Fixes #48. Add test and split func Use nanoseconds instead Call onEvicted if item existed before setting Call onEvicted if item.Expired
This commit is contained in:
parent
46f4078530
commit
38560f59f4
13
cache.go
13
cache.go
|
@ -57,7 +57,15 @@ func (c *cache) Set(k string, x interface{}, d time.Duration) {
|
|||
if d > 0 {
|
||||
e = time.Now().Add(d).UnixNano()
|
||||
}
|
||||
|
||||
var item Item
|
||||
var evicted bool
|
||||
|
||||
c.mu.Lock()
|
||||
if c.onEvicted != nil {
|
||||
item, evicted = c.items[k]
|
||||
}
|
||||
|
||||
c.items[k] = Item{
|
||||
Object: x,
|
||||
Expiration: e,
|
||||
|
@ -65,6 +73,11 @@ func (c *cache) Set(k string, x interface{}, d time.Duration) {
|
|||
// TODO: Calls to mu.Unlock are currently not deferred because defer
|
||||
// adds ~200 ns (as of go1.)
|
||||
c.mu.Unlock()
|
||||
|
||||
// try to call onEvicted if key existed before but it was expired before cleanup
|
||||
if evicted && item.Expired() {
|
||||
c.onEvicted(k, item.Object)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) set(k string, x interface{}, d time.Duration) {
|
||||
|
|
|
@ -1247,6 +1247,39 @@ func TestOnEvicted(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestOnEvictedCalledBeforeSet(t *testing.T) {
|
||||
tc := New(DefaultExpiration, 0)
|
||||
expiry := 1 * time.Nanosecond
|
||||
|
||||
works := false
|
||||
tc.OnEvicted(func(k string, v interface{}) {
|
||||
if k == "foo" && v.(int) == 3 {
|
||||
|
||||
works = true
|
||||
}
|
||||
tc.Set("bar", 4, DefaultExpiration)
|
||||
})
|
||||
|
||||
tc.Set("foo", 3, expiry)
|
||||
if tc.onEvicted == nil {
|
||||
t.Fatal("tc.onEvicted is nil")
|
||||
}
|
||||
|
||||
// ensure item expires
|
||||
time.Sleep(expiry)
|
||||
|
||||
// calling Set again should evict expired item
|
||||
tc.Set("foo", 3, DefaultExpiration)
|
||||
|
||||
x, _ := tc.Get("bar")
|
||||
if !works {
|
||||
t.Fatal("works bool not true")
|
||||
}
|
||||
if x.(int) != 4 {
|
||||
t.Error("bar was not 4")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheSerialization(t *testing.T) {
|
||||
tc := New(DefaultExpiration, 0)
|
||||
testFillAndSerialize(t, tc)
|
||||
|
|
Loading…
Reference in New Issue