Skip to content

Commit 9766960

Browse files
Add Support for PreviousTTL (#121)
1 parent a91502b commit 9766960

File tree

4 files changed

+48
-6
lines changed

4 files changed

+48
-6
lines changed

cache.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ func (c *Cache[K, V]) set(key K, value V, ttl time.Duration) *Item[K, V] {
148148
c.evict(EvictionReasonCapacityReached, c.items.lru.Back())
149149
}
150150

151+
if ttl == PreviousOrDefaultTTL {
152+
ttl = c.options.ttl
153+
}
154+
151155
// create a new item
152156
item := newItem(key, value, ttl, c.options.enableVersionTracking)
153157
elem = c.items.lru.PushFront(item)

cache_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ func Test_Cache_set(t *testing.T) {
189189
Key: existingKey,
190190
TTL: DefaultTTL,
191191
},
192+
"Set with existing key and PreviousOrDefaultTTL": {
193+
Key: existingKey,
194+
TTL: PreviousOrDefaultTTL,
195+
},
192196
"Set with new key and eviction caused by small capacity": {
193197
Capacity: 3,
194198
Key: newKey,
@@ -232,6 +236,14 @@ func Test_Cache_set(t *testing.T) {
232236
},
233237
ExpectFns: true,
234238
},
239+
"Set with new key and PreviousOrDefaultTTL": {
240+
Key: newKey,
241+
TTL: PreviousOrDefaultTTL,
242+
Metrics: Metrics{
243+
Insertions: 1,
244+
},
245+
ExpectFns: true,
246+
},
235247
}
236248

237249
for cn, c := range cc {
@@ -245,6 +257,9 @@ func Test_Cache_set(t *testing.T) {
245257
evictionFnsCalls int
246258
)
247259

260+
// calculated based on how addToCache sets ttl
261+
existingKeyTTL := time.Hour + time.Minute
262+
248263
cache := prepCache(time.Hour, evictedKey, existingKey, "test3")
249264
cache.options.capacity = c.Capacity
250265
cache.options.ttl = time.Minute * 20
@@ -295,6 +310,13 @@ func Test_Cache_set(t *testing.T) {
295310
assert.Equal(t, c.TTL, item.ttl)
296311
assert.WithinDuration(t, time.Now(), item.expiresAt, c.TTL)
297312
assert.Equal(t, c.Key, cache.items.expQueue[0].Value.(*Item[string, string]).key)
313+
case c.TTL == PreviousOrDefaultTTL:
314+
expectedTTL := cache.options.ttl
315+
if c.Key == existingKey {
316+
expectedTTL = existingKeyTTL
317+
}
318+
assert.Equal(t, expectedTTL, item.ttl)
319+
assert.WithinDuration(t, time.Now(), item.expiresAt, expectedTTL)
298320
default:
299321
assert.Equal(t, c.TTL, item.ttl)
300322
assert.Zero(t, item.expiresAt)

item.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ const (
99
// NoTTL indicates that an item should never expire.
1010
NoTTL time.Duration = -1
1111

12+
// PreviousOrDefaultTTL indicates that existing TTL of item should be used
13+
// default TTL will be used as fallback if item doesn't exist
14+
PreviousOrDefaultTTL time.Duration = -2
15+
1216
// DefaultTTL indicates that the default TTL value of the cache
1317
// instance should be used.
1418
DefaultTTL time.Duration = 0
@@ -58,17 +62,23 @@ func (item *Item[K, V]) update(value V, ttl time.Duration) {
5862
defer item.mu.Unlock()
5963

6064
item.value = value
65+
66+
// update version if enabled
67+
if item.version > -1 {
68+
item.version++
69+
}
70+
71+
// no need to update ttl or expiry in this case
72+
if ttl == PreviousOrDefaultTTL {
73+
return
74+
}
75+
6176
item.ttl = ttl
6277

6378
// reset expiration timestamp because the new TTL may be
6479
// 0 or below
6580
item.expiresAt = time.Time{}
6681
item.touchUnsafe()
67-
68-
// update version if enabled
69-
if item.version > -1 {
70-
item.version++
71-
}
7282
}
7383

7484
// touch updates the item's expiration timestamp.

item_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,16 @@ func Test_Item_update(t *testing.T) {
3131
assert.Equal(t, int64(1), item.version)
3232
assert.WithinDuration(t, time.Now().Add(time.Hour), item.expiresAt, time.Minute)
3333

34+
item.update("previous ttl", PreviousOrDefaultTTL)
35+
assert.Equal(t, "previous ttl", item.value)
36+
assert.Equal(t, time.Hour, item.ttl)
37+
assert.Equal(t, int64(2), item.version)
38+
assert.WithinDuration(t, time.Now().Add(time.Hour), item.expiresAt, time.Minute)
39+
3440
item.update("hi", NoTTL)
3541
assert.Equal(t, "hi", item.value)
3642
assert.Equal(t, NoTTL, item.ttl)
37-
assert.Equal(t, int64(2), item.version)
43+
assert.Equal(t, int64(3), item.version)
3844
assert.Zero(t, item.expiresAt)
3945
}
4046

0 commit comments

Comments
 (0)