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 {
|
if d > 0 {
|
||||||
e = time.Now().Add(d).UnixNano()
|
e = time.Now().Add(d).UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var item Item
|
||||||
|
var evicted bool
|
||||||
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
if c.onEvicted != nil {
|
||||||
|
item, evicted = c.items[k]
|
||||||
|
}
|
||||||
|
|
||||||
c.items[k] = Item{
|
c.items[k] = Item{
|
||||||
Object: x,
|
Object: x,
|
||||||
Expiration: e,
|
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
|
// TODO: Calls to mu.Unlock are currently not deferred because defer
|
||||||
// adds ~200 ns (as of go1.)
|
// adds ~200 ns (as of go1.)
|
||||||
c.mu.Unlock()
|
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) {
|
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) {
|
func TestCacheSerialization(t *testing.T) {
|
||||||
tc := New(DefaultExpiration, 0)
|
tc := New(DefaultExpiration, 0)
|
||||||
testFillAndSerialize(t, tc)
|
testFillAndSerialize(t, tc)
|
||||||
|
|
Loading…
Reference in New Issue