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 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() b.Lock()
bkt, exists := b.buckets[primary] bkt, exists := b.buckets[primary]
if exists == false { if exists == false {
@ -46,7 +46,7 @@ func (b *layeredBucket) set(primary, secondary string, value interface{}, durati
b.buckets[primary] = bkt b.buckets[primary] = bkt
} }
b.Unlock() b.Unlock()
item, existing := bkt.set(secondary, value, duration, false) item, existing := bkt.set(secondary, value, duration, track)
item.group = primary item.group = primary
return item, existing return item, existing
} }

View file

@ -102,9 +102,14 @@ func (c *LayeredCache) TrackingGet(primary, secondary string) TrackedItem {
return item 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 // Set the value in the cache for the specified duration
func (c *LayeredCache) Set(primary, secondary string, value interface{}, duration time.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. // 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 { if err != nil {
return nil, err 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. // 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() go c.worker()
} }
func (c *LayeredCache) set(primary, secondary string, value interface{}, duration time.Duration) *Item { 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) item, existing := c.bucket(primary).set(primary, secondary, value, duration, track)
if existing != nil { if existing != nil {
c.deletables <- existing c.deletables <- existing
} }

View file

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