public async Task <SearchResult <IPackageSearchMetadata> > RefreshSearchAsync(RefreshToken refreshToken, CancellationToken cancellationToken) { var searchToken = refreshToken as AggregatedRefreshToken; if (searchToken == null) { throw new InvalidOperationException("Invalid token"); } return(await WaitForCompletionOrBailOutAsync( searchToken.SearchString, searchToken.SearchTasks, searchToken.TelemetryState, cancellationToken)); }
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); }
public Task <SearchResult <IPackageSearchMetadata> > RefreshSearchAsync(RefreshToken refreshToken, CancellationToken cancellationToken) => Task.FromResult(SearchResult.Empty <IPackageSearchMetadata>());