File: LanguageClient\ViewCodeCommandHandler.FileExistsHelper.cs
Web Access
Project: src\src\Razor\src\Razor\src\Microsoft.VisualStudio.LanguageServices.Razor\Microsoft.VisualStudio.LanguageServices.Razor.csproj (Microsoft.VisualStudio.LanguageServices.Razor)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using Microsoft.AspNetCore.Razor;
 
namespace Microsoft.VisualStudio.Razor.LanguageClient;
 
internal sealed partial class ViewCodeCommandHandler
{
    /// <summary>
    /// Simple helper that caches <see cref="File.Exists"/> results and evicts a results after
    /// <see cref="MaxMilliseconds"/> have passed.
    /// </summary>
    private readonly struct FileExistsHelper
    {
        private const int MaxMilliseconds = 10000;
 
        private readonly Stopwatch _watch;
        private readonly Dictionary<string, (bool Exists, long Milliseconds)> _cache;
 
        public FileExistsHelper()
        {
            _watch = Stopwatch.StartNew();
            _cache = new(PathUtilities.OSSpecificPathComparer);
        }
 
        public bool FileExists(string filePath)
        {
            var currentMilliseconds = _watch.ElapsedMilliseconds;
 
            // Calculate if we've never seen this file path or its cached value has expired.
            if (!_cache.TryGetValue(filePath, out var value) || CachedValueExpired(currentMilliseconds, value.Milliseconds))
            {
                var exists = File.Exists(filePath);
                value = (exists, currentMilliseconds);
                _cache[filePath] = value;
            }
 
            return value.Exists;
 
            static bool CachedValueExpired(long currentMilliseconds, long cachedMilliseconds)
            {
                return currentMilliseconds - cachedMilliseconds > MaxMilliseconds;
            }
        }
    }
}