Search code examples
c#.net-corememorycache

MemoryCache EvictionCallback never called


.NET Core MemoryCache. I would like to be notified when an item is removed from cache. Having implemented this sample: Cache in-memory in ASP.NET Core.

=> CreateCallbackEntry(). When I put a breakpoint within

Eviction callback:

private static void EvictionCallback(object key, object value,
    EvictionReason reason, object state)
{
    var message = $"Entry was evicted. Reason: {reason}.";
    // i should reach this after 10 seconds
}

the breakpoint is ONLY hit when trying read that same key again that was just stored in cache. Otherwise that eviction method never gets called even though the web page stays open.

Controller:

    public void OnGet()
    {
        _cache.GetOrCreate("key", item);
        
        // eviction callback does not fire until I query for the same key again below
        var t = _cache.GetOrCreate("key", item)
    }

Cache:

var cacheEntryOptions = new MemoryCacheEntryOptions()
    .SetAbsoluteExpiration(TimeSpan.FromSeconds(10))
    .RegisterPostEvictionCallback(callback: EvictionCallback, state: this);

cacheEntry = await createItem();
_cache.Set(key, cacheEntry, cacheEntryOptions);

Solution

  • The PostEvicionCallback is not an event for expiration.

    The callback is executed when the cache entry is removed from the cache, not on expiration.

    The removal of expired entries is done lazily after expiration upon an action on the cache. This is why the callback executed on your next request after expiration. For performance considerations we remove expired items in batches which has a minimum period specified by MemoryCacheOptions.ExpirationScanFrequency.

    We do not currently expose any mechanism to notify exactly when cache entries expire but expired entries will eventually trigger the expiration callback some time in the future after any cache operation.

    From github.com/aspnet/Caching

    You can try lowering the MemoryCacheOptions.ExpirationScanFrequency, but beware of the performance impact. Default value is 1 minute.