alastairtree / LazyCache

An easy to use thread safe in-memory caching service with a simple developer friendly API for c#
https://nuget.org/packages/LazyCache
MIT License
1.72k stars 159 forks source link

Cache hit callback when calling GetOrAdd #147

Closed onetocny closed 3 years ago

onetocny commented 3 years ago

[Use the Thumbs Up reaction to vote for this feature, and please avoid adding comments like "+1" as they create noise for others watching the issue.]

Hello. First of all let me thank you for LazyCache library. I would like to ask if there is a way how to detect that value was loaded from cache when calling GetOrAdd and GetOrAddAsync? So far I was not able to find if this is possible. For example same pattern as for PostEvictionCallbacks would be nice.

alastairtree commented 3 years ago

Why not just flip a bool in the cached delegate if it executes?

// Create the cache
IAppCache cache = new CachingService();

// Get all products from the cache, or get from db and cache results
bool cacheHit = true;
var products = cache.GetOrAdd("productService-getProducts", () =>  {
  cacheHit = false;
  return dbContext.Products.ToList();
});

// now cacheHit: true => result came from the cache
// and cacheHit: false => result came from the db
onetocny commented 3 years ago

Yes, thank you. This is something that I was thinking about. I had on mind some more convenient way such as following extension method:

public static async Task<T> GetOrAddAsync<T>(this IAppCache cache, string key, Func<Task<T>> addItemFactory, Action<T> cacheHitHandler, MemoryCacheEntryOptions policy)
{
    var cacheHit = true;
    var result = await cache.GetOrAddAsync(key, async () =>
    {
        cacheHit = false;
        return await addItemFactory();
    }, policy);

    if (cacheHit)
    {
        cacheHitHandler(result);
    }

    return result;
}

Or better I would create new property in MemoryCacheEntryOptions for cache hit callback so that no new parameter would be needed.

alastairtree commented 3 years ago

I think if you need this it best lives in your own extension method which as you have shown is very easy to do. Most people (inc me!) will not require it.