From f84b6cbde3b9a532a51740c05e9f20b97e8d37ff Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Tue, 1 Dec 2020 09:59:22 +0100 Subject: [PATCH] AbsoluteExpirationRelativeToNow can internally just use AbsoluteExpiration and current time --- .../src/CacheEntry.cs | 7 ++-- .../src/MemoryCache.cs | 33 ++++++------------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/CacheEntry.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/CacheEntry.cs index 82d09639ca0f8..e8b27a608e5d6 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/CacheEntry.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/CacheEntry.cs @@ -21,7 +21,6 @@ internal class CacheEntry : ICacheEntry private IList _expirationTokenRegistrations; private IList _postEvictionCallbacks; private IList _expirationTokens; - private TimeSpan? _absoluteExpirationRelativeToNow; private TimeSpan? _slidingExpiration; private long? _size; private IDisposable _scope; @@ -45,8 +44,10 @@ internal CacheEntry(object key, MemoryCache memoryCache) /// public TimeSpan? AbsoluteExpirationRelativeToNow { - get => _absoluteExpirationRelativeToNow; - set => _absoluteExpirationRelativeToNow = value > TimeSpan.Zero ? value : throw new ArgumentOutOfRangeException(nameof(AbsoluteExpirationRelativeToNow), value, "The relative expiration value must be positive."); + get => AbsoluteExpiration.HasValue ? AbsoluteExpiration.Value - _cache.GetUtcNow() : null; + set => AbsoluteExpiration = value > TimeSpan.Zero + ? (_cache.GetUtcNow() + value) + : throw new ArgumentOutOfRangeException(nameof(AbsoluteExpirationRelativeToNow), value, "The relative expiration value must be positive."); } /// diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs index 903f270b1a54d..06047024e9ab9 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs @@ -57,13 +57,7 @@ public MemoryCache(IOptions optionsAccessor, ILoggerFactory _logger = loggerFactory.CreateLogger(); _entries = new ConcurrentDictionary(); - - if (_options.Clock == null) - { - _options.Clock = new SystemClock(); - } - - _lastExpirationScan = _options.Clock.UtcNow; + _lastExpirationScan = _options.Clock?.UtcNow ?? DateTimeOffset.UtcNow; } /// @@ -96,6 +90,8 @@ public ICacheEntry CreateEntry(object key) return new CacheEntry(key, this); } + internal DateTimeOffset GetUtcNow() => _options.Clock?.UtcNow ?? DateTimeOffset.UtcNow; + internal void SetEntry(CacheEntry entry) { if (_disposed) @@ -109,17 +105,7 @@ internal void SetEntry(CacheEntry entry) throw new InvalidOperationException($"Cache entry must specify a value for {nameof(entry.Size)} when {nameof(_options.SizeLimit)} is set."); } - DateTimeOffset utcNow = _options.Clock.UtcNow; - - DateTimeOffset? absoluteExpiration = null; - if (entry.AbsoluteExpirationRelativeToNow.HasValue) - { - absoluteExpiration = utcNow + entry.AbsoluteExpirationRelativeToNow; - } - else if (entry.AbsoluteExpiration.HasValue) - { - absoluteExpiration = entry.AbsoluteExpiration; - } + DateTimeOffset? absoluteExpiration = entry.AbsoluteExpiration; // Applying the option's absolute expiration only if it's not already smaller. // This can be the case if a dependent cache entry has a smaller value, and @@ -132,6 +118,7 @@ internal void SetEntry(CacheEntry entry) } } + DateTimeOffset utcNow = GetUtcNow(); // Initialize the last access timestamp at the time the entry is added entry.LastAccessed = utcNow; @@ -227,7 +214,7 @@ public bool TryGetValue(object key, out object result) ValidateCacheKey(key); CheckDisposed(); - DateTimeOffset utcNow = _options.Clock.UtcNow; + DateTimeOffset utcNow = GetUtcNow(); if (_entries.TryGetValue(key, out CacheEntry entry)) { @@ -279,7 +266,7 @@ public void Remove(object key) entry.InvokeEvictionCallbacks(); } - StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow); + StartScanForExpiredItemsIfNeeded(GetUtcNow()); } private void RemoveEntry(CacheEntry entry) @@ -298,7 +285,7 @@ internal void EntryExpired(CacheEntry entry) { // TODO: For efficiency consider processing these expirations in batches. RemoveEntry(entry); - StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow); + StartScanForExpiredItemsIfNeeded(GetUtcNow()); } // Called by multiple actions to see how long it's been since we last checked for expired items. @@ -321,7 +308,7 @@ void ScheduleTask(DateTimeOffset utcNow) private static void ScanForExpiredItems(MemoryCache cache) { - DateTimeOffset now = cache._lastExpirationScan = cache._options.Clock.UtcNow; + DateTimeOffset now = cache._lastExpirationScan = cache.GetUtcNow(); foreach (CacheEntry entry in cache._entries.Values) { if (entry.CheckExpired(now)) @@ -404,7 +391,7 @@ private void Compact(long removalSizeTarget, Func computeEntry long removedSize = 0; // Sort items by expired & priority status - DateTimeOffset now = _options.Clock.UtcNow; + DateTimeOffset now = GetUtcNow(); foreach (CacheEntry entry in _entries.Values) { if (entry.CheckExpired(now))