add TrackingSet to LayeredCache

This commit is contained in:
Karl Seguin 2020-08-14 11:15:13 +08:00
parent f3b2b9fd88
commit 0dbf3f125f
4 changed files with 19 additions and 11 deletions

View file

@ -38,7 +38,7 @@ func (b *layeredBucket) getSecondaryBucket(primary string) *bucket {
return bucket
}
func (b *layeredBucket) set(primary, secondary string, value interface{}, duration time.Duration) (*Item, *Item) {
func (b *layeredBucket) set(primary, secondary string, value interface{}, duration time.Duration, track bool) (*Item, *Item) {
b.Lock()
bkt, exists := b.buckets[primary]
if exists == false {
@ -46,7 +46,7 @@ func (b *layeredBucket) set(primary, secondary string, value interface{}, durati
b.buckets[primary] = bkt
}
b.Unlock()
item, existing := bkt.set(secondary, value, duration, false)
item, existing := bkt.set(secondary, value, duration, track)
item.group = primary
return item, existing
}

View file

@ -102,9 +102,14 @@ func (c *LayeredCache) TrackingGet(primary, secondary string) TrackedItem {
return item
}
// Set the value in the cache for the specified duration
func (c *LayeredCache) TrackingSet(primary, secondary string, value interface{}, duration time.Duration) TrackedItem {
return c.set(primary, secondary, value, duration, true)
}
// Set the value in the cache for the specified duration
func (c *LayeredCache) Set(primary, secondary string, value interface{}, duration time.Duration) {
c.set(primary, secondary, value, duration)
c.set(primary, secondary, value, duration, false)
}
// Replace the value if it exists, does not set if it doesn't.
@ -131,7 +136,7 @@ func (c *LayeredCache) Fetch(primary, secondary string, duration time.Duration,
if err != nil {
return nil, err
}
return c.set(primary, secondary, value, duration), nil
return c.set(primary, secondary, value, duration, false), nil
}
// Remove the item from the cache, return true if the item was present, false otherwise.
@ -193,8 +198,8 @@ func (c *LayeredCache) restart() {
go c.worker()
}
func (c *LayeredCache) set(primary, secondary string, value interface{}, duration time.Duration) *Item {
item, existing := c.bucket(primary).set(primary, secondary, value, duration)
func (c *LayeredCache) set(primary, secondary string, value interface{}, duration time.Duration, track bool) *Item {
item, existing := c.bucket(primary).set(primary, secondary, value, duration, track)
if existing != nil {
c.deletables <- existing
}

View file

@ -196,17 +196,20 @@ func (_ LayeredCacheTests) PromotedItemsDontGetPruned() {
func (_ LayeredCacheTests) TrackerDoesNotCleanupHeldInstance() {
cache := Layered(Configure().ItemsToPrune(10).Track())
for i := 0; i < 10; i++ {
item0 := cache.TrackingSet("0", "a", 0, time.Minute)
for i := 1; i < 11; i++ {
cache.Set(strconv.Itoa(i), "a", i, time.Minute)
}
item := cache.TrackingGet("0", "a")
item1 := cache.TrackingGet("1", "a")
time.Sleep(time.Millisecond * 10)
gcLayeredCache(cache)
Expect(cache.Get("0", "a").Value()).To.Equal(0)
Expect(cache.Get("1", "a")).To.Equal(nil)
item.Release()
Expect(cache.Get("1", "a").Value()).To.Equal(1)
item0.Release()
item1.Release()
gcLayeredCache(cache)
Expect(cache.Get("0", "a")).To.Equal(nil)
Expect(cache.Get("1", "a")).To.Equal(nil)
}
func (_ LayeredCacheTests) RemovesOldestItemWhenFull() {

View file

@ -143,7 +143,7 @@ user := item.Value() //will be nil if "user:4" didn't exist in the cache
item.Release() //can be called even if item.Value() returned nil
```
In practice, `Release` wouldn't be called until later, at some other place in your code.
In practice, `Release` wouldn't be called until later, at some other place in your code. `TrackingSet` can be used to set a value to be tracked.
There's a couple reason to use the tracking mode if other parts of your code also hold references to objects. First, if you're already going to hold a reference to these objects, there's really no reason not to have them in the cache - the memory is used up anyways.