Closed eli-darkly closed 3 years ago
fetch
doesn't do anything fancy (e.g., there's no singleflight mechanism), so it isn't too burdensome to re-implement it in your app to behave how you want.
Essentially, fetch is currently:
item := c.Get(key)
if item != nil && !item.Expired() {
return item, nil
}
value, err := fetch()
if err != nil {
return nil, err
}
return c.set(key, value, duration, false), nil
You could simply remove the item.Expired() check:
item := c.Get(key)
if item != nil {
return item, nil
}
value, err := fetch()
if err != nil {
return nil, err
}
return c.set(key, value, duration, false), nil
As-is, items are only evicted when the cache is full. Alternative, I'd recommend just using a very large ttl:
const MAX_TTL = time.Duration(1<<63 - 1)
Fair enough. As I mentioned in my comment on the other issue, I'd recommend updating the doc comment on Fetch to clarify that it's not doing anything you can't do exactly as well with Get and Set (I wasn't 100% sure at first because it's calling the private set
rather than the exported Set
—that's also the case above, so your example code wouldn't actually compile if implemented outside the package—but when I followed through to the implementation of set
I could see that there's nothing special there).
Unless I'm missing something, the current implementation requires that all items have a finite TTL. That's fine for many use cases, but if I'm caching the results of some expensive computation that won't change over time for any given key, then I really wouldn't ever want values to be evicted (or recomputed by
Fetch
) simply because they're old— I would only want LRU entries to be evicted due to the cache being too full. I'd like to be able to specify a zero or negativetime.Duration
to mean "this doesn't expire."