Description
Description
👋🏽 Wanted to preface this by saying: First time opening an issue here, please correct me if I misspeak.
This issue stems from the implementation of the Microsoft.Extensions.Caching.Memory
package, and from the looks of it, specifically on CacheEntry
. While looking into this issue, I wanted to make sure someone else hadn't already reported it, but the closest I could find regarding this exact issue is a question (posted here).
When setting an absolute expiration, it makes sense that when that expiration passes, the object is removed, and this behavior also extends to sliding expirations, of which presumably get reset when the value is retrieved. This is fine, expected, and documented behavior. The documentation seems to be lacking in the nuance of sliding expirations, though.
If a sliding expiration is set, and an absolute expiration is absent, the sliding expiration then acts as an "absolute" expiration (from the time the object is inserted, it seems?). This is slightly confusing, at least to myself, since if the object is never "accessed", the sliding expiration cannot kick in.
Reproduction Steps
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
namespace MinimalRepro;
public static class Program
{
public static async Task Main()
{
var services = new ServiceCollection();
services.AddMemoryCache();
var provider = services.BuildServiceProvider();
var cache = provider.GetRequireService<IMemoryCache>();
var cacheOptions = new new MemoryCacheEntryOptions()
cacheOptions.SetSlidingExpiration(TimeSpan.FromSeconds(5));
cache.Set("example_key", "example_value", cacheOptions);
await Task.Delay(TimeSpan.FromSeconds(5));
var keyExists = cache.TryGetValue("example_key", out _);
if (!keyExists)
Console.WriteLine("The cached value has gone missing!");
}
}
Expected behavior
The expiration timer is started when the value is initially accessed.
Actual behavior
The object will expire from cache regardless of whether it's been "accessed"; this is likely due to the LastAccessed
property of a CacheEntry being a non-nullable DateTime
, which appears to default to 1/1/0001 12:00:00 AM
.
Regression?
I'm unsure, but I'm doubtful of it.
Known Workarounds
No response
Configuration
.NET 6.0.100
Windows 10, 21H1, 64-bit.
This issue should be platform-agnostic.
Other information
The issue is within this code, and I believe is due to the issue regarding the datetime being initialized with a default value that will almost always be greater than the expiration, or so I'd hope 😄.
While I wouldn't say that this is a bug or incorrect behavior, I think at the very least the documentation (MSDN Link) should be updated to reflect this otherwise undocumented behavior.