Skip to content

Commit

Permalink
merge: patrickmn#66
Browse files Browse the repository at this point in the history
  • Loading branch information
Carseason authored Jun 8, 2024
1 parent 46f4078 commit 5f3d8bd
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
35 changes: 35 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,38 @@ func (c *cache) SetDefault(k string, x interface{}) {
c.Set(k, x, DefaultExpiration)
}

// Update the expiration on an item in the cache Update the expiration an item
// from the cache. Returns the previous expiration time if one is set (if the
// item never expires a zero value for time.Time is returned), and a
// bool indicating whether the key was found.
func (c *cache) UpdateExpiration(k string, d time.Duration) (time.Time, bool) {
c.mu.Lock()
// "Inlining" of get and Expired
item, found := c.items[k]
if !found {
c.mu.Unlock()
return time.Time{}, false
}

if item.Expiration > 0 {
if time.Now().UnixNano() > item.Expiration {
c.mu.Unlock()
return time.Time{}, false
}
}

c.set(k, item.Object, d)
c.mu.Unlock()

if item.Expiration > 0 {
return time.Unix(0, item.Expiration), true
}

// If expiration <= 0 (i.e. no expiration time set) then return a zeroed
// time.Time
return time.Time{}, true
}

// Add an item to the cache only if an item doesn't already exist for the given
// key, or if the existing item has expired. Returns an error otherwise.
func (c *cache) Add(k string, x interface{}, d time.Duration) error {
Expand Down Expand Up @@ -1159,3 +1191,6 @@ func New(defaultExpiration, cleanupInterval time.Duration) *Cache {
func NewFrom(defaultExpiration, cleanupInterval time.Duration, items map[string]Item) *Cache {
return newCacheWithJanitor(defaultExpiration, cleanupInterval, items)
}



95 changes: 95 additions & 0 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1769,3 +1769,98 @@ func TestGetWithExpiration(t *testing.T) {
t.Error("expiration for e is in the past")
}
}

func TestUpdateExpiration(t *testing.T) {
tc := New(50*time.Millisecond, 1*time.Millisecond)

tc.Set("a", 1, DefaultExpiration)
x, e1, found := tc.GetWithExpiration("a")
if !found {
t.Error("did not find a")
}
if x != 1 {
t.Error("a should be 1; value:", x)
}

tc.Increment("a", 1)
x, e2, found := tc.GetWithExpiration("a")
if !found {
t.Error("did not find a2")
}
if x != 2 {
t.Error("a2 should be 2; value:", x)
}
if e1 != e2 {
t.Error("expiration changed when it should not have")
}

<-time.After(5*time.Millisecond)
tc.Increment("a", 1)
e3, found := tc.UpdateExpiration("a", DefaultExpiration)
if !found {
t.Error("did not find a3")
}
if e1 != e3 {
t.Error("did not get previous expiration back; e1:", e1, "e3:", e3)
}
x, e3, found = tc.GetWithExpiration("a")
if !found {
t.Error("did not find a3")
}
if x != 3 {
t.Error("a3 should be 3; value:", x)
}
if e1 == e3 {
t.Error("should have different expiration but did not change")
}
if e3.UnixNano() != tc.items["a"].Expiration {
t.Error("expiration for a3 is not the correct time")
}
if e3.UnixNano() < time.Now().UnixNano() {
t.Error("expiration for a3 is in the past")
}

_, found = tc.UpdateExpiration("a", NoExpiration)
if !found {
t.Error("did not find a4")
}
_, e, found := tc.GetWithExpiration("a")
if !found {
t.Error("did not find a4 a second time")
}
if !e.IsZero() {
t.Error("expiration for a4 is not a zeroed time")
}

_, found = tc.UpdateExpiration("a", 50*time.Millisecond)
if !found {
t.Error("did not find a5")
}
_, e, found = tc.GetWithExpiration("a")
if !found {
t.Error("did not find a5 a second time")
}
if e.UnixNano() != tc.items["a"].Expiration {
t.Error("expiration for a5 is not the correct time")
}
if e.UnixNano() < time.Now().UnixNano() {
t.Error("expiration for a5 is in the past")
}

<-time.After(49*time.Millisecond)
_, found = tc.Get("a")
if !found {
t.Error("did not find a6")
}

<-time.After(2*time.Millisecond)
_, found = tc.Get("a")
if found {
t.Error("found a7, but it should have expired")
}

_, found = tc.UpdateExpiration("a", DefaultExpiration)
if found {
t.Error("found a8, but it should have expired")
}
}

0 comments on commit 5f3d8bd

Please sign in to comment.