jellydator / ttlcache

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

Way to get expired elements. #103

Closed cmsong-shina closed 11 months ago

cmsong-shina commented 1 year ago

I know I can clear expired elements via the .DeleteExpired() method. My question is, is there a way to get the expired elements?

Right now I am using it as a vendor module by adding the following method.

// PopExpired deletes and return all expired items from the cache.
func (c *Cache[K, V]) PopExpired() []V {
    c.items.mu.Lock()
    defer c.items.mu.Unlock()

    if c.items.expQueue.isEmpty() {
        return nil
    }

    expired := make([]V, 0)

    e := c.items.expQueue[0]
    for e.Value.(*Item[K, V]).isExpiredUnsafe() {
        c.evict(EvictionReasonExpired, e)

        expired = append(expired, e.Value.(*Item[K, V]).value)

        if c.items.expQueue.isEmpty() {
            break
        }

        // expiration queue has a new root
        e = c.items.expQueue[0]
    }

    return expired
}

Do you think this is a safe and reasonable implementation, and if so, can we add it to the official API?

davseby commented 1 year ago

You can use OnEviction method. DeleteExpired is the only method that uses the EvictionReasonExpired reason, which can be used to identify deleted items.

Something like this:

// c is a Cache instance.
cleanup := c.OnEviction(func(ctx context.Context, er ttlcache.EvictionReason, i *ttlcache.Item[string, string]) {
    if er != ttlcache.EvictionReasonExpired {
        return
    }

    // do something with the expired item.
})

// once we no longer need to track the evicted items, we can remove the callback function.
defer cleanup()

c.DeleteExpired()
davseby commented 11 months ago

There is a way to do it.