public async ValueTask <List <MetricSnapshot> > LoadHistoryAsync(string repoOwner, string repoName)
        {
            if (string.IsNullOrWhiteSpace(repoOwner))
            {
                throw new ArgumentNullException(nameof(repoOwner));
            }

            if (string.IsNullOrWhiteSpace(repoName))
            {
                throw new ArgumentNullException(nameof(repoName));
            }

            const string searchPattern = "*" + _analysisSuffix;
            var          searchPath    = GetPathToRepoDataFiles(repoOwner, repoName);

            string[] matches;
            try
            {
                matches = _fs.DirectoryGetFiles(searchPath, searchPattern);
            }
            catch (DirectoryNotFoundException)
            {
                // DirectoryNotFound is normal when trying to read analytics from a WatchedRepo that was just added, and has never been analyzed or cached
                return(null);
            }

            if (matches.Length < 1)
            {
                return(new List <MetricSnapshot>());
            }

            var readMatches = matches
                              .Select(async p => await _fs.FileReadAllTextAsync(p))
                              .ToList();
            await Task.WhenAll(readMatches);

            var deserialized = readMatches
                               .Select(t => t.Result)
                               .Select(s => JsonConvert.DeserializeObject <MetricSnapshot>(s, _jsonSerializerSettings))
                               .ToList();

            return(deserialized);
        }