Merge 71bfe9e709
into 7ac151875f
This commit is contained in:
commit
7f7e45ecd4
45
cache.go
45
cache.go
|
@ -42,6 +42,7 @@ type cache struct {
|
||||||
items map[string]Item
|
items map[string]Item
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
onEvicted func(string, interface{})
|
onEvicted func(string, interface{})
|
||||||
|
onEvictedBulk func([]KeyAndValue)
|
||||||
janitor *janitor
|
janitor *janitor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +116,22 @@ func (c *cache) Replace(k string, x interface{}, d time.Duration) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update only if it is already existing, keep same ttl
|
||||||
|
// Set new expiry time which is now - its expiration
|
||||||
|
func (c *cache) Update(k string, x interface{}) error {
|
||||||
|
c.mu.Lock()
|
||||||
|
_, found := c.get(k)
|
||||||
|
if !found {
|
||||||
|
c.mu.Unlock()
|
||||||
|
return fmt.Errorf("Item %s doesn't exist", k)
|
||||||
|
}
|
||||||
|
newTtl := time.Unix(0, c.items[k].Expiration)
|
||||||
|
c.set(k, x, newTtl.Sub(time.Now()))
|
||||||
|
c.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get an item from the cache. Returns the item or nil, and a bool indicating
|
// Get an item from the cache. Returns the item or nil, and a bool indicating
|
||||||
// whether the key was found.
|
// whether the key was found.
|
||||||
func (c *cache) Get(k string) (interface{}, bool) {
|
func (c *cache) Get(k string) (interface{}, bool) {
|
||||||
|
@ -922,14 +939,14 @@ func (c *cache) delete(k string) (interface{}, bool) {
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
type keyAndValue struct {
|
type KeyAndValue struct {
|
||||||
key string
|
Key string
|
||||||
value interface{}
|
Value interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all expired items from the cache.
|
// Delete all expired items from the cache.
|
||||||
func (c *cache) DeleteExpired() {
|
func (c *cache) DeleteExpired() {
|
||||||
var evictedItems []keyAndValue
|
var evictedItems []KeyAndValue
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
for k, v := range c.items {
|
for k, v := range c.items {
|
||||||
|
@ -937,13 +954,20 @@ func (c *cache) DeleteExpired() {
|
||||||
if v.Expiration > 0 && now > v.Expiration {
|
if v.Expiration > 0 && now > v.Expiration {
|
||||||
ov, evicted := c.delete(k)
|
ov, evicted := c.delete(k)
|
||||||
if evicted {
|
if evicted {
|
||||||
evictedItems = append(evictedItems, keyAndValue{k, ov})
|
evictedItems = append(evictedItems, KeyAndValue{k, ov})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
|
// Call evict functions only when
|
||||||
|
// their respective functions exist.
|
||||||
|
if c.onEvictedBulk != nil{
|
||||||
|
c.onEvictedBulk(evictedItems)
|
||||||
|
}else if c.onEvicted != nil{
|
||||||
for _, v := range evictedItems {
|
for _, v := range evictedItems {
|
||||||
c.onEvicted(v.key, v.value)
|
c.onEvicted(v.Key, v.Value)
|
||||||
|
}
|
||||||
|
}else{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,6 +980,15 @@ func (c *cache) OnEvicted(f func(string, interface{})) {
|
||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set an optional OnEvictedBulk which will be used to evict keys in bulk
|
||||||
|
// This is used when eviction happens in bulk when expiry is checked at
|
||||||
|
// regular intervals, we dont want to call onEvict multiple times
|
||||||
|
func (c *cache) OnEvictedBulk(f func([]KeyAndValue)) {
|
||||||
|
c.mu.Lock()
|
||||||
|
c.onEvictedBulk = f
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// Write the cache's items (using Gob) to an io.Writer.
|
// Write the cache's items (using Gob) to an io.Writer.
|
||||||
//
|
//
|
||||||
// NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
|
// NOTE: This method is deprecated in favor of c.Items() and NewFrom() (see the
|
||||||
|
|
|
@ -1137,6 +1137,25 @@ func TestReplace(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdate(t *testing.T) {
|
||||||
|
tc := New(75*time.Millisecond, 1*time.Millisecond)
|
||||||
|
tc.Set("a", 1, DefaultExpiration)
|
||||||
|
|
||||||
|
<-time.After(50 * time.Millisecond)
|
||||||
|
_, found := tc.Get("a")
|
||||||
|
if !found {
|
||||||
|
t.Error("error in update; didnt find value that was expected")
|
||||||
|
}
|
||||||
|
|
||||||
|
tc.Update("a", 2)
|
||||||
|
<-time.After(26 * time.Millisecond)
|
||||||
|
|
||||||
|
a, found := tc.Get("a")
|
||||||
|
if found || a != nil {
|
||||||
|
t.Error("Getting A found value that shouldn't exist:", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestDelete(t *testing.T) {
|
func TestDelete(t *testing.T) {
|
||||||
tc := New(DefaultExpiration, 0)
|
tc := New(DefaultExpiration, 0)
|
||||||
tc.Set("foo", "bar", DefaultExpiration)
|
tc.Set("foo", "bar", DefaultExpiration)
|
||||||
|
|
Loading…
Reference in New Issue