jellydator / ttlcache

An in-memory cache with item expiration and generics
MIT License
883 stars 115 forks source link

Set doesn't reset TTL if the key already exists #136

Open vsavicks opened 2 months ago

vsavicks commented 2 months ago

According to the docs of the Set() method:

If an item associated with the provided key already exists, the new item overwrites the existing one.

However, if I try to set an item that already exists but has an expired TTL and delete all expired, the newly set item also gets deleted:

package main

import (
    "fmt"
    "time"

    "github.com/jellydator/ttlcache/v3"
)

func main() {
    cache := ttlcache.New[string](
        ttlcache.WithTTL[string, string](1 * time.Second),
    )
    cache.Set("foo", "bar", ttlcache.DefaultTTL)
    fmt.Printf("first: %s\n", cache.Keys())

    time.Sleep(2 * time.Second)
    fmt.Printf("after 2s: %s\n", cache.Keys())

    cache.DeleteExpired()
    fmt.Printf("after delete: %s\n", cache.Keys())

    cache.Set("baz", "qux", ttlcache.DefaultTTL)
    fmt.Printf("new: %s\n", cache.Keys())

    time.Sleep(2 * time.Second)
    fmt.Printf("after 2s: %s\n", cache.Keys())

    cache.Set("baz", "qum", ttlcache.DefaultTTL)
    cache.DeleteExpired()
    fmt.Printf("after set and delete: %s\n", cache.Keys())
}

Output:

first: [foo]
after 2s: [foo]
after delete: []
new: [baz]
after 2s: [baz]
after set and delete: []

I would expect the replaced item to have new TTL and not get deleted by DeleteExpired() call.

swithek commented 1 month ago

Thanks for reporting this @vsavicks. We'll try to have it fixed soon.