sm
/
cache
1
0
Fork 0
This commit is contained in:
pranjal5215 2017-04-19 10:36:08 +00:00 committed by GitHub
commit 7f7e45ecd4
2 changed files with 59 additions and 7 deletions

View File

@ -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()
for _, v := range evictedItems { // Call evict functions only when
c.onEvicted(v.key, v.value) // their respective functions exist.
if c.onEvictedBulk != nil{
c.onEvictedBulk(evictedItems)
}else if c.onEvicted != nil{
for _, v := range evictedItems {
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

View File

@ -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)