Skip to content

Commit

Permalink
Delete expired items before setting
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jaimem88 committed Oct 14, 2020
1 parent 46f4078 commit 38560f5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
13 changes: 13 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,27 @@ 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,
}
// 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) {
Expand Down
33 changes: 33 additions & 0 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 38560f5

Please sign in to comment.