private async Task AutoClearLoopAsync <TKey, TEntity>(IEntityCache <TKey, TEntity> cache, string optionsName, IBatchingStore store, CancellationToken cancellationToken = default) where TEntity : IEntity <TKey> { CachingOptions options = _cachingOptions.Get(optionsName); if (options.Lifetime < TimeSpan.Zero) { _log.LogDebug("{ServiceName} cache lifetime set to 0 or lower, cache purges disabled", cache.GetType().Name); return; } _log.LogDebug("{ServiceName} starting cache auto-clear loop with rate of {ClearRate}", cache.GetType().Name, options.Lifetime); while (!cancellationToken.IsCancellationRequested) { await Task.Delay(options.Lifetime, cancellationToken).ConfigureAwait(false); // flush batch to prevent data loss store?.FlushBatch(); // find and remove entities from cache IEnumerable <TEntity> expired = cache.Find(e => e.IsExpired(options.Lifetime)); foreach (TEntity entity in expired) { cache.Remove(entity.ID); } _log.LogDebug("{RemovedCount} expired {ServiceName} entities removed from cache", expired.Count(), cache.GetType().Name); } }