diff --git a/src/Foundatio/Caching/InMemoryCacheClient.cs b/src/Foundatio/Caching/InMemoryCacheClient.cs index 45e5ea20..4e6b84b7 100644 --- a/src/Foundatio/Caching/InMemoryCacheClient.cs +++ b/src/Foundatio/Caching/InMemoryCacheClient.cs @@ -195,8 +195,7 @@ public Task RemoveByPrefixAsync(string prefix) internal void RemoveExpiredKey(string key, bool sendNotification = true) { - // Consideration: We could reduce the amount of calls to this by updating the key and only having maintenance run this. - // Consideration: We could also only remove expired items after a last access period determined when any property on the model is updated. + // Consideration: We could reduce the amount of calls to this by updating ExpiresAt and only having maintenance remove keys. if (_memory.TryGetValue(key, out var existingEntry) && existingEntry.ExpiresAt < SystemClock.UtcNow) { if (_memory.TryRemove(key, out var removedEntry)) @@ -223,7 +222,6 @@ public Task> GetAsync(string key) if (existingEntry.ExpiresAt < SystemClock.UtcNow) { - RemoveExpiredKey(key); Interlocked.Increment(ref _misses); return Task.FromResult(CacheValue.NoValue); } @@ -801,16 +799,19 @@ public Task ExistsAsync(string key) if (String.IsNullOrEmpty(key)) return Task.FromException(new ArgumentNullException(nameof(key), "Key cannot be null or empty.")); - if (!_memory.TryGetValue(key, out var cacheEntry)) + if (!_memory.TryGetValue(key, out var existingEntry)) { Interlocked.Increment(ref _misses); return Task.FromResult(false); } - Interlocked.Increment(ref _hits); - if (cacheEntry.ExpiresAt < SystemClock.UtcNow) + if (existingEntry.ExpiresAt < SystemClock.UtcNow) + { + Interlocked.Increment(ref _misses); return Task.FromResult(false); + } + Interlocked.Increment(ref _hits); return Task.FromResult(true); } @@ -819,19 +820,20 @@ public Task ExistsAsync(string key) if (String.IsNullOrEmpty(key)) throw new ArgumentNullException(nameof(key), "Key cannot be null or empty"); - if (!_memory.TryGetValue(key, out var value) || value.ExpiresAt == DateTime.MaxValue) + if (!_memory.TryGetValue(key, out var existingEntry) || existingEntry.ExpiresAt == DateTime.MaxValue) { Interlocked.Increment(ref _misses); return Task.FromResult(null); } - Interlocked.Increment(ref _hits); - if (value.ExpiresAt >= SystemClock.UtcNow) - return Task.FromResult(value.ExpiresAt.Subtract(SystemClock.UtcNow)); - - RemoveExpiredKey(key); + if (existingEntry.ExpiresAt < SystemClock.UtcNow || existingEntry.ExpiresAt == DateTime.MaxValue) + { + Interlocked.Increment(ref _misses); + return Task.FromResult(null); + } - return Task.FromResult(null); + Interlocked.Increment(ref _hits); + return Task.FromResult(existingEntry.ExpiresAt.Subtract(SystemClock.UtcNow)); } public async Task SetExpirationAsync(string key, TimeSpan expiresIn) @@ -847,9 +849,9 @@ public async Task SetExpirationAsync(string key, TimeSpan expiresIn) } Interlocked.Increment(ref _writes); - if (_memory.TryGetValue(key, out var value)) + if (_memory.TryGetValue(key, out var existingEntry)) { - value.ExpiresAt = expiresAt; + existingEntry.ExpiresAt = expiresAt; await StartMaintenanceAsync().AnyContext(); } }