Adding support for OnDelete callback function
OnDelete will receive an item that is being processed for deletion to support calling cleanup function specific to the item stored
This commit is contained in:
parent
72059a01e9
commit
7421e2d7b4
5 changed files with 66 additions and 1 deletions
3
cache.go
3
cache.go
|
@ -186,6 +186,9 @@ func (c *Cache) doDelete(item *Item) {
|
||||||
item.promotions = -2
|
item.promotions = -2
|
||||||
} else {
|
} else {
|
||||||
c.size -= item.size
|
c.size -= item.size
|
||||||
|
if c.onDelete != nil {
|
||||||
|
c.onDelete(item)
|
||||||
|
}
|
||||||
c.list.Remove(item.element)
|
c.list.Remove(item.element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,28 @@ func (_ CacheTests) DeletesAValue() {
|
||||||
Expect(cache.Get("worm").Value()).To.Equal("sand")
|
Expect(cache.Get("worm").Value()).To.Equal("sand")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ CacheTests) OnDeleteCallbackCalled() {
|
||||||
|
|
||||||
|
onDeleteFnCalled := false
|
||||||
|
onDeleteFn := func(item *Item) {
|
||||||
|
if item.key == "spice" {
|
||||||
|
onDeleteFnCalled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cache := New(Configure().OnDelete(onDeleteFn))
|
||||||
|
cache.Set("spice", "flow", time.Minute)
|
||||||
|
cache.Set("worm", "sand", time.Minute)
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 10) // Run once to init
|
||||||
|
cache.Delete("spice")
|
||||||
|
time.Sleep(time.Millisecond * 10) // Wait for worker to pick up deleted items
|
||||||
|
|
||||||
|
Expect(cache.Get("spice")).To.Equal(nil)
|
||||||
|
Expect(cache.Get("worm").Value()).To.Equal("sand")
|
||||||
|
Expect(onDeleteFnCalled).To.Equal(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (_ CacheTests) FetchesExpiredItems() {
|
func (_ CacheTests) FetchesExpiredItems() {
|
||||||
cache := New(Configure())
|
cache := New(Configure())
|
||||||
fn := func() (interface{}, error) { return "moo-moo", nil }
|
fn := func() (interface{}, error) { return "moo-moo", nil }
|
||||||
|
|
|
@ -8,6 +8,7 @@ type Configuration struct {
|
||||||
promoteBuffer int
|
promoteBuffer int
|
||||||
getsPerPromote int32
|
getsPerPromote int32
|
||||||
tracking bool
|
tracking bool
|
||||||
|
onDelete func(item *Item)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates a configuration object with sensible defaults
|
// Creates a configuration object with sensible defaults
|
||||||
|
@ -92,3 +93,11 @@ func (c *Configuration) Track() *Configuration {
|
||||||
c.tracking = true
|
c.tracking = true
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnDelete allows setting a callback function to react to ideam deletion.
|
||||||
|
// This typically allows to do a cleanup of resources, such as calling a Close() on
|
||||||
|
// cached object that require some kind of tear-down.
|
||||||
|
func (c *Configuration) OnDelete(callback func(item *Item)) *Configuration {
|
||||||
|
c.onDelete = callback
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
|
@ -195,6 +195,9 @@ func (c *LayeredCache) worker() {
|
||||||
item.promotions = -2
|
item.promotions = -2
|
||||||
} else {
|
} else {
|
||||||
c.size -= item.size
|
c.size -= item.size
|
||||||
|
if c.onDelete != nil {
|
||||||
|
c.onDelete(item)
|
||||||
|
}
|
||||||
c.list.Remove(item.element)
|
c.list.Remove(item.element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package ccache
|
package ccache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/karlseguin/expect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
. "github.com/karlseguin/expect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LayeredCacheTests struct{}
|
type LayeredCacheTests struct{}
|
||||||
|
@ -65,6 +66,33 @@ func (_ *LayeredCacheTests) DeletesAValue() {
|
||||||
Expect(cache.Get("leto", "sister").Value()).To.Equal("ghanima")
|
Expect(cache.Get("leto", "sister").Value()).To.Equal("ghanima")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *LayeredCacheTests) OnDeleteCallbackCalled() {
|
||||||
|
|
||||||
|
onDeleteFnCalled := false
|
||||||
|
onDeleteFn := func(item *Item) {
|
||||||
|
|
||||||
|
if item.group == "spice" && item.key == "flow" {
|
||||||
|
onDeleteFnCalled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cache := Layered(Configure().OnDelete(onDeleteFn))
|
||||||
|
cache.Set("spice", "flow", "value-a", time.Minute)
|
||||||
|
cache.Set("spice", "must", "value-b", time.Minute)
|
||||||
|
cache.Set("leto", "sister", "ghanima", time.Minute)
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 10) // Run once to init
|
||||||
|
cache.Delete("spice", "flow")
|
||||||
|
time.Sleep(time.Millisecond * 10) // Wait for worker to pick up deleted items
|
||||||
|
|
||||||
|
Expect(cache.Get("spice", "flow")).To.Equal(nil)
|
||||||
|
Expect(cache.Get("spice", "must").Value()).To.Equal("value-b")
|
||||||
|
Expect(cache.Get("spice", "worm")).To.Equal(nil)
|
||||||
|
Expect(cache.Get("leto", "sister").Value()).To.Equal("ghanima")
|
||||||
|
|
||||||
|
Expect(onDeleteFnCalled).To.Equal(true)
|
||||||
|
}
|
||||||
|
|
||||||
func (_ *LayeredCacheTests) DeletesALayer() {
|
func (_ *LayeredCacheTests) DeletesALayer() {
|
||||||
cache := newLayered()
|
cache := newLayered()
|
||||||
cache.Set("spice", "flow", "value-a", time.Minute)
|
cache.Set("spice", "flow", "value-a", time.Minute)
|
||||||
|
|
Loading…
Reference in a new issue