private async Task <HashSet <string> > UpdateVersionListsAsync(List <IdAndValue <ResultAndAccessCondition <VersionListData> > > allFinished) { if (_developmentOptions.Value.DisableVersionListWriters) { _logger.LogWarning( "Skipped updating {VersionListCount} version lists.", allFinished.Count); return(new HashSet <string>(StringComparer.OrdinalIgnoreCase)); } var versionListIdSample = allFinished .OrderByDescending(x => x.Value.Result.VersionProperties.Count(v => v.Value.Listed)) .Select(x => x.Id) .Take(5) .ToArray(); var workerCount = Math.Min(allFinished.Count, _options.Value.MaxConcurrentVersionListWriters); _logger.LogInformation( "Updating {VersionListCount} version lists with {WorkerCount} workers, including {IdSample}.", allFinished.Count, workerCount, versionListIdSample); var work = new ConcurrentBag <IdAndValue <ResultAndAccessCondition <VersionListData> > >(allFinished); var failedPackageIds = new ConcurrentQueue <string>(); using (_telemetryService.TrackVersionListsUpdated(allFinished.Count, workerCount)) { var tasks = Enumerable .Range(0, workerCount) .Select(async x => { await Task.Yield(); while (work.TryTake(out var finished)) { var success = await _versionListDataClient.TryReplaceAsync( finished.Id, finished.Value.Result, finished.Value.AccessCondition); if (!success) { failedPackageIds.Enqueue(finished.Id); } } }) .ToList(); await Task.WhenAll(tasks); _logger.LogInformation( "Done updating {VersionListCount} version lists. {FailureCount} version lists failed.", allFinished.Count - failedPackageIds.Count, failedPackageIds.Count); return(failedPackageIds.ToHashSet(StringComparer.OrdinalIgnoreCase)); } }
private async Task UpdateVersionListsAsync(List <IdAndValue <ResultAndAccessCondition <VersionListData> > > allFinished) { if (_developmentOptions.Value.DisableVersionListWriters) { _logger.LogWarning( "Skipped updating {VersionListCount} version lists.", allFinished.Count); return; } var versionListIdSample = allFinished .OrderByDescending(x => x.Value.Result.VersionProperties.Count(v => v.Value.Listed)) .Select(x => x.Id) .Take(5) .ToArray(); var workerCount = Math.Min(allFinished.Count, _options.Value.MaxConcurrentVersionListWriters); _logger.LogInformation( "Updating {VersionListCount} version lists with {WorkerCount} workers, including {IdSample}.", allFinished.Count, workerCount, versionListIdSample); var work = new ConcurrentBag <IdAndValue <ResultAndAccessCondition <VersionListData> > >(allFinished); using (_telemetryService.TrackVersionListsUpdated(allFinished.Count, workerCount)) { var tasks = Enumerable .Range(0, workerCount) .Select(async x => { await Task.Yield(); while (work.TryTake(out var finished)) { // This method can throw a storage exception if the version list has changed. await _versionListDataClient.ReplaceAsync( finished.Id, finished.Value.Result, finished.Value.AccessCondition); } }) .ToList(); await Task.WhenAll(tasks); _logger.LogInformation("Done updating {VersionListCount} version lists.", allFinished.Count); } }