private async Task <SearchResult <IPackageSearchMetadata> > WaitForCompletionOrBailOutAsync( string searchText, IDictionary <string, Task <SearchResult <IPackageSearchMetadata> > > searchTasks, CancellationToken cancellationToken) { if (searchTasks.Count == 0) { return(SearchResult.Empty <IPackageSearchMetadata>()); } var aggregatedTask = Task.WhenAll(searchTasks.Values); RefreshToken refreshToken = null; if (aggregatedTask != await Task.WhenAny(aggregatedTask, Task.Delay(DefaultTimeout))) { refreshToken = new AggregatedRefreshToken { SearchString = searchText, SearchTasks = searchTasks, RetryAfter = DefaultTimeout }; } var partitionedTasks = searchTasks .ToLookup(t => t.Value.Status == TaskStatus.RanToCompletion); var completedOnly = partitionedTasks[true]; SearchResult <IPackageSearchMetadata> aggregated; if (completedOnly.Any()) { var results = await Task.WhenAll(completedOnly.Select(kv => kv.Value)); aggregated = await AggregateSearchResultsAsync(searchText, results); } else { aggregated = SearchResult.Empty <IPackageSearchMetadata>(); } aggregated.RefreshToken = refreshToken; var notCompleted = partitionedTasks[false]; if (notCompleted.Any()) { aggregated.SourceSearchStatus .AddRange(notCompleted .ToDictionary(kv => kv.Key, kv => GetLoadingStatus(kv.Value.Status))); } // Observe the aggregate task exception to prevent an unhandled exception. // The individual task exceptions are logged in LogError and will be reported // in the Add Packages dialog. var ex = aggregatedTask.Exception; return(aggregated); }
private async Task <SearchResult <IPackageSearchMetadata> > WaitForCompletionOrBailOutAsync( string searchText, IDictionary <string, Task <SearchResult <IPackageSearchMetadata> > > searchTasks, CancellationToken cancellationToken) { if (searchTasks.Count == 0) { return(SearchResult.Empty <IPackageSearchMetadata>()); } var aggregatedTask = Task.WhenAll(searchTasks.Values); RefreshToken refreshToken = null; if (aggregatedTask != await Task.WhenAny(aggregatedTask, Task.Delay(DefaultTimeout))) { refreshToken = new AggregatedRefreshToken { SearchString = searchText, SearchTasks = searchTasks, RetryAfter = DefaultTimeout }; } var partitionedTasks = searchTasks .ToLookup(t => t.Value.Status == TaskStatus.RanToCompletion); var completedOnly = partitionedTasks[true]; SearchResult <IPackageSearchMetadata> aggregated; if (completedOnly.Any()) { var results = await Task.WhenAll(completedOnly.Select(kv => kv.Value)); aggregated = await AggregateSearchResultsAsync(searchText, results); } else { aggregated = SearchResult.Empty <IPackageSearchMetadata>(); } aggregated.RefreshToken = refreshToken; var notCompleted = partitionedTasks[false]; if (notCompleted.Any()) { aggregated.SourceSearchStatus .AddRange(notCompleted .ToDictionary(kv => kv.Key, kv => GetLoadingStatus(kv.Value.Status))); } return(aggregated); }
private async Task <SearchResult <IPackageSearchMetadata> > WaitForCompletionOrBailOutAsync( string searchText, IDictionary <string, Task <SearchResult <IPackageSearchMetadata> > > searchTasks, TelemetryState telemetryState, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); if (searchTasks.Count == 0) { return(SearchResult.Empty <IPackageSearchMetadata>()); } var aggregatedTask = Task.WhenAll(searchTasks.Values); RefreshToken refreshToken = null; if (aggregatedTask != await Task.WhenAny(aggregatedTask, Task.Delay(DefaultTimeout))) { refreshToken = new AggregatedRefreshToken { TelemetryState = telemetryState, SearchString = searchText, SearchTasks = searchTasks, RetryAfter = DefaultTimeout }; } var partitionedTasks = searchTasks .ToLookup(t => t.Value.Status == TaskStatus.RanToCompletion); var completedOnly = partitionedTasks[true]; SearchResult <IPackageSearchMetadata> aggregated; IEnumerable <TimeSpan> timings = null; var timeAggregation = new Stopwatch(); if (completedOnly.Any()) { var results = await Task.WhenAll(completedOnly.Select(kv => kv.Value)); timings = results.Select(e => e.Duration); timeAggregation.Start(); aggregated = await AggregateSearchResultsAsync(searchText, results, telemetryState); timeAggregation.Stop(); } else { timings = Enumerable.Empty <TimeSpan>(); aggregated = SearchResult.Empty <IPackageSearchMetadata>(); } aggregated.OperationId = telemetryState?.OperationId; aggregated.RefreshToken = refreshToken; var notCompleted = partitionedTasks[false]; if (notCompleted.Any()) { var statuses = notCompleted.ToDictionary( kv => kv.Key, kv => GetLoadingStatus(kv.Value.Status)); foreach (var item in statuses) { aggregated.SourceSearchStatus.Add(item); } var exceptions = notCompleted .Where(kv => kv.Value.Exception != null) .ToDictionary( kv => kv.Key, kv => (Exception)kv.Value.Exception); foreach (var item in exceptions) { aggregated.SourceSearchException.Add(item); } } if (_telemetryService != null && aggregated.SourceSearchStatus != null && aggregated.SourceSearchStatus.Values != null && telemetryState != null) { var loadingStatus = aggregated.SourceSearchStatus.Values.Aggregate(); if (loadingStatus != LoadingStatus.Loading && telemetryState.ShouldEmit) { telemetryState.Duration.Stop(); _telemetryService.EmitTelemetryEvent(new SearchPageTelemetryEvent( telemetryState.OperationId, telemetryState.PageIndex, aggregated.Items?.Count ?? 0, telemetryState.Duration.Elapsed, timings, timeAggregation.Elapsed, loadingStatus)); } } return(aggregated); }
private async Task<SearchResult<IPackageSearchMetadata>> WaitForCompletionOrBailOutAsync( string searchText, IDictionary<string, Task<SearchResult<IPackageSearchMetadata>>> searchTasks, CancellationToken cancellationToken) { if (searchTasks.Count == 0) { return SearchResult.Empty<IPackageSearchMetadata>(); } var aggregatedTask = Task.WhenAll(searchTasks.Values); RefreshToken refreshToken = null; if (aggregatedTask != await Task.WhenAny(aggregatedTask, Task.Delay(DefaultTimeout))) { refreshToken = new AggregatedRefreshToken { SearchString = searchText, SearchTasks = searchTasks, RetryAfter = DefaultTimeout }; } var partitionedTasks = searchTasks .ToLookup(t => t.Value.Status == TaskStatus.RanToCompletion); var completedOnly = partitionedTasks[true]; SearchResult<IPackageSearchMetadata> aggregated; if (completedOnly.Any()) { var results = await Task.WhenAll(completedOnly.Select(kv => kv.Value)); aggregated = await AggregateSearchResultsAsync(searchText, results); } else { aggregated = SearchResult.Empty<IPackageSearchMetadata>(); } aggregated.RefreshToken = refreshToken; var notCompleted = partitionedTasks[false]; if (notCompleted.Any()) { aggregated.SourceSearchStatus .AddRange(notCompleted .ToDictionary(kv => kv.Key, kv => GetLoadingStatus(kv.Value.Status))); } return aggregated; }