I have stumbled upon a similar issue. It looks that HttpRuntime.Cache
takes the liberty of removing items from cache when it "feels" that there is not enough memory. This happens even if CacheItemPriority.NotRemovable
priority is provided along with no absolute/no sliding expiration and under normal application domain operation (no shutdown).
How to catch actual expiration
HttpRuntime.Cache
provides a remove callback to be used when an item is removed. Of course, in order to filter out normal evictions on application pool shutdown, System.Web.Hosting.HostingEnvironment.ShutdownReason
should be checked.
public class ApplicationPoolService : IApplicationPoolService
{
public bool IsShuttingDown()
{
return System.Web.Hosting.HostingEnvironment.ShutdownReason != ApplicationShutdownReason.None;
}
}
private void ReportRemovedCallback(string key, object value, CacheItemRemovedReason reason)
{
if (!ApplicationPoolService.IsShuttingDown())
{
var str = $"Removed cached item with key {key} and count {(value as IDictionary)?.Count}, reason {reason}";
LoggingService.Log(LogLevel.Info, str);
}
}
HttpRuntime.Cache.Insert(CacheDictKey, dict, dependencies: null,
absoluteExpiration: DateTime.Now.AddMinutes(absoluteExpiration),
slidingExpiration: slidingExpiration <= 0 ? Cache.NoSlidingExpiration : TimeSpan.FromMinutes(slidingExpiration),
priority: CacheItemPriority.NotRemovable,
onRemoveCallback: ReportRemovedCallback);
Alternative
MemoryCache can be used as a good replacement for HttpRuntime.Cache
. It provides very similar functionality. A full analysis can be read here.