replace is size-aware
This commit is contained in:
17
bucket.go
17
bucket.go
@@ -22,13 +22,12 @@ func (b *bucket) set(key string, value interface{}, duration time.Duration) (*It
|
|||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
if existing, exists := b.lookup[key]; exists {
|
if existing, exists := b.lookup[key]; exists {
|
||||||
s := existing.size
|
|
||||||
existing.value = value
|
existing.value = value
|
||||||
existing.expires = expires
|
existing.expires = expires
|
||||||
d := int64(0)
|
d := int64(0)
|
||||||
if sized, ok := value.(Sized); ok {
|
if sized, ok := value.(Sized); ok {
|
||||||
newSize := sized.Size()
|
newSize := sized.Size()
|
||||||
d = newSize - s
|
d = newSize - existing.size
|
||||||
if d != 0 {
|
if d != 0 {
|
||||||
atomic.StoreInt64(&existing.size, newSize)
|
atomic.StoreInt64(&existing.size, newSize)
|
||||||
}
|
}
|
||||||
@@ -40,15 +39,23 @@ func (b *bucket) set(key string, value interface{}, duration time.Duration) (*It
|
|||||||
return item, true, int64(item.size)
|
return item, true, int64(item.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bucket) replace(key string, value interface{}) bool {
|
func (b *bucket) replace(key string, value interface{}) (bool, int64) {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
existing, exists := b.lookup[key]
|
existing, exists := b.lookup[key]
|
||||||
if exists == false {
|
if exists == false {
|
||||||
return false
|
return false, 0
|
||||||
|
}
|
||||||
|
d := int64(0)
|
||||||
|
if sized, ok := value.(Sized); ok {
|
||||||
|
newSize := sized.Size()
|
||||||
|
d = newSize - existing.size
|
||||||
|
if d != 0 {
|
||||||
|
atomic.StoreInt64(&existing.size, newSize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
existing.value = value
|
existing.value = value
|
||||||
return true
|
return true, d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bucket) delete(key string) *Item {
|
func (b *bucket) delete(key string) *Item {
|
||||||
|
6
cache.go
6
cache.go
@@ -82,7 +82,11 @@ func (c *Cache) Set(key string, value interface{}, duration time.Duration) {
|
|||||||
// Returns true if the item existed an was replaced, false otherwise.
|
// Returns true if the item existed an was replaced, false otherwise.
|
||||||
// Replace does not reset item's TTL nor does it alter its position in the LRU
|
// Replace does not reset item's TTL nor does it alter its position in the LRU
|
||||||
func (c *Cache) Replace(key string, value interface{}) bool {
|
func (c *Cache) Replace(key string, value interface{}) bool {
|
||||||
return c.bucket(key).replace(key, value)
|
exists, d := c.bucket(key).replace(key, value)
|
||||||
|
if d != 0 {
|
||||||
|
atomic.AddInt64(&c.size, d)
|
||||||
|
}
|
||||||
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempts to get the value from the cache and calles fetch on a miss.
|
// Attempts to get the value from the cache and calles fetch on a miss.
|
||||||
|
@@ -102,6 +102,30 @@ func (_ CacheTests) SetUpdatesSizeOnDelta() {
|
|||||||
Expect(cache.size).To.Equal(int64(2))
|
Expect(cache.size).To.Equal(int64(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ CacheTests) ReplaceDoesNotchangeSizeIfNotSet() {
|
||||||
|
cache := New(Configure())
|
||||||
|
cache.Set("1", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("2", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("3", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Replace("4", &SizedItem{1, 2})
|
||||||
|
Expect(cache.size).To.Equal(int64(6))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ CacheTests) ReplaceChangesSize() {
|
||||||
|
cache := New(Configure())
|
||||||
|
cache.Set("1", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("2", &SizedItem{1, 2}, time.Minute)
|
||||||
|
|
||||||
|
cache.Replace("2", &SizedItem{1, 2})
|
||||||
|
Expect(cache.size).To.Equal(int64(4))
|
||||||
|
|
||||||
|
cache.Replace("2", &SizedItem{1, 1})
|
||||||
|
Expect(cache.size).To.Equal(int64(3))
|
||||||
|
|
||||||
|
cache.Replace("2", &SizedItem{1, 3})
|
||||||
|
Expect(cache.size).To.Equal(int64(5))
|
||||||
|
}
|
||||||
|
|
||||||
type SizedItem struct {
|
type SizedItem struct {
|
||||||
id int
|
id int
|
||||||
s int64
|
s int64
|
||||||
|
@@ -35,12 +35,12 @@ func (b *layeredBucket) set(primary, secondary string, value interface{}, durati
|
|||||||
return item, new, d
|
return item, new, d
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *layeredBucket) replace(primary, secondary string, value interface{}) bool {
|
func (b *layeredBucket) replace(primary, secondary string, value interface{}) (bool, int64) {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
bucket, exists := b.buckets[primary]
|
bucket, exists := b.buckets[primary]
|
||||||
b.Unlock()
|
b.Unlock()
|
||||||
if exists == false {
|
if exists == false {
|
||||||
return false
|
return false, 0
|
||||||
}
|
}
|
||||||
return bucket.replace(secondary, value)
|
return bucket.replace(secondary, value)
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,11 @@ func (c *LayeredCache) Set(primary, secondary string, value interface{}, duratio
|
|||||||
// Returns true if the item existed an was replaced, false otherwise.
|
// Returns true if the item existed an was replaced, false otherwise.
|
||||||
// Replace does not reset item's TTL nor does it alter its position in the LRU
|
// Replace does not reset item's TTL nor does it alter its position in the LRU
|
||||||
func (c *LayeredCache) Replace(primary, secondary string, value interface{}) bool {
|
func (c *LayeredCache) Replace(primary, secondary string, value interface{}) bool {
|
||||||
return c.bucket(primary).replace(primary, secondary, value)
|
exists, d := c.bucket(primary).replace(primary, secondary, value)
|
||||||
|
if d != 0 {
|
||||||
|
atomic.AddInt64(&c.size, d)
|
||||||
|
}
|
||||||
|
return exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempts to get the value from the cache and calles fetch on a miss.
|
// Attempts to get the value from the cache and calles fetch on a miss.
|
||||||
|
@@ -171,3 +171,27 @@ func (_ LayeredCacheTests) SetUpdatesSizeOnDelta() {
|
|||||||
time.Sleep(time.Millisecond * 10)
|
time.Sleep(time.Millisecond * 10)
|
||||||
Expect(cache.size).To.Equal(int64(5))
|
Expect(cache.size).To.Equal(int64(5))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ LayeredCacheTests) ReplaceDoesNotchangeSizeIfNotSet() {
|
||||||
|
cache := Layered(Configure())
|
||||||
|
cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("pri", "3", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Replace("sec", "3", &SizedItem{1, 2})
|
||||||
|
Expect(cache.size).To.Equal(int64(6))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ LayeredCacheTests) ReplaceChangesSize() {
|
||||||
|
cache := Layered(Configure())
|
||||||
|
cache.Set("pri", "1", &SizedItem{1, 2}, time.Minute)
|
||||||
|
cache.Set("pri", "2", &SizedItem{1, 2}, time.Minute)
|
||||||
|
|
||||||
|
cache.Replace("pri", "2", &SizedItem{1, 2})
|
||||||
|
Expect(cache.size).To.Equal(int64(4))
|
||||||
|
|
||||||
|
cache.Replace("pri", "2", &SizedItem{1, 1})
|
||||||
|
Expect(cache.size).To.Equal(int64(3))
|
||||||
|
|
||||||
|
cache.Replace("pri", "2", &SizedItem{1, 3})
|
||||||
|
Expect(cache.size).To.Equal(int64(5))
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user