Пример #1
0
        public async Task <SearchResult <IPackageSearchMetadata> > ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken)
        {
            var searchToken = continuationToken as AggregatedContinuationToken;

            if (searchToken?.SourceSearchCursors == null)
            {
                throw new InvalidOperationException("Invalid token");
            }

            var searchTokens = _sourceRepositories
                               .Join(searchToken.SourceSearchCursors,
                                     r => r.PackageSource.Name,
                                     c => c.Key,
                                     (r, c) => new { Repository = r, NextToken = c.Value });

            var searchTasks = TaskCombinators.ObserveErrorsAsync(
                searchTokens,
                j => j.Repository.PackageSource.Name,
                (j, t) => j.Repository.SearchAsync(j.NextToken, PageSize, t),
                LogError,
                cancellationToken);

            return(await WaitForCompletionOrBailOutAsync(
                       searchToken.SearchString,
                       searchTasks,
                       searchToken.TelemetryState?.NextPage(),
                       cancellationToken));
        }
        public async Task<SearchResult<IPackageSearchMetadata>> SearchAsync(string searchText, SearchFilter filter, CancellationToken cancellationToken)
        {
            var searchOperationId = Guid.NewGuid();
            if (_telemetryService != null)
            {
                _telemetryService.EmitTelemetryEvent(new SearchTelemetryEvent(
                    searchOperationId,
                    searchText,
                    filter.IncludePrerelease));

                _telemetryService.EmitTelemetryEvent(SourceTelemetry.GetSearchSourceSummaryEvent(
                    searchOperationId,
                    _sourceRepositories.Select(x => x.PackageSource)));
            }

            var searchTasks = TaskCombinators.ObserveErrorsAsync(
                _sourceRepositories,
                r => r.PackageSource.Name,
                (r, t) => r.SearchAsync(searchText, filter, PageSize, t),
                LogError,
                cancellationToken);

            return await WaitForCompletionOrBailOutAsync(
                searchText,
                searchTasks,
                new TelemetryState(searchOperationId, pageIndex: 0),
                cancellationToken);
        }
Пример #3
0
        public override async Task <SearchResult <IPackageSearchMetadata> > ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken)
        {
            var searchToken = continuationToken as FeedSearchContinuationToken;

            if (searchToken == null)
            {
                throw new InvalidOperationException("Invalid token");
            }

            var packagesNeedingConsolidation = _installedPackages
                                               .GroupById()
                                               .Where(g => g.Count() > 1)
                                               .Select(g => new PackageIdentity(g.Key, g.Max()))
                                               .ToArray();

            var packages = packagesNeedingConsolidation
                           .Where(p => p.Id.IndexOf(searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
                           .OrderBy(p => p.Id)
                           .Skip(searchToken.StartIndex)
                           .Take(PageSize + 1)
                           .ToArray();

            var hasMoreItems = packages.Length > PageSize;

            if (hasMoreItems)
            {
                packages = packages.Take(packages.Length - 1).ToArray();
            }

            var items = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => _metadataProvider.GetPackageMetadataAsync(p, searchToken.SearchFilter.IncludePrerelease, t),
                cancellationToken);

            var result = SearchResult.FromItems(items.ToArray());

            var loadingStatus = hasMoreItems
                ? LoadingStatus.Ready
                : packages.Length == 0
                ? LoadingStatus.NoItemsFound
                : LoadingStatus.NoMoreItems;

            result.SourceSearchStatus = new Dictionary <string, LoadingStatus>
            {
                { "Consolidate", loadingStatus }
            };

            if (hasMoreItems)
            {
                result.NextToken = new FeedSearchContinuationToken
                {
                    SearchString = searchToken.SearchString,
                    SearchFilter = searchToken.SearchFilter,
                    StartIndex   = searchToken.StartIndex + packages.Length
                };
            }

            return(result);
        }
Пример #4
0
        public override async Task <SearchResult <IPackageSearchMetadata> > ContinueSearchAsync(ContinuationToken continuationToken, CancellationToken cancellationToken)
        {
            var searchToken = continuationToken as FeedSearchContinuationToken;

            if (searchToken == null)
            {
                throw new InvalidOperationException("Invalid token");
            }

            var packages = _installedPackages
                           .GetLatest()
                           .Where(p => p.Id.IndexOf(searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1)
                           .OrderBy(p => p.Id)
                           .Skip(searchToken.StartIndex)
                           .Take(PageSize + 1)
                           .ToArray();

            var hasMoreItems = packages.Length > PageSize;

            if (hasMoreItems)
            {
                packages = packages.Take(packages.Length - 1).ToArray();
            }

            var items = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => GetPackageMetadataAsync(p, searchToken.SearchFilter.IncludePrerelease, t),
                cancellationToken);

            //  The packages were originally sorted which is important because we Skip and Take based on that sort
            //  however the asynchronous execution has randomly reordered the set. So we need to resort.
            var result = SearchResult.FromItems(items.OrderBy(p => p.Identity.Id).ToArray());

            var loadingStatus = hasMoreItems
                ? LoadingStatus.Ready
                : packages.Length == 0
                ? LoadingStatus.NoItemsFound
                : LoadingStatus.NoMoreItems;

            result.SourceSearchStatus = new Dictionary <string, LoadingStatus>
            {
                { "Installed", loadingStatus }
            };

            if (hasMoreItems)
            {
                result.NextToken = new FeedSearchContinuationToken
                {
                    SearchString = searchToken.SearchString,
                    SearchFilter = searchToken.SearchFilter,
                    StartIndex   = searchToken.StartIndex + packages.Length
                };
            }

            return(result);
        }
        public async Task <SearchResult <IPackageSearchMetadata> > SearchAsync(string searchText, SearchFilter filter, CancellationToken cancellationToken)
        {
            var searchTasks = TaskCombinators.ObserveErrorsAsync(
                _sourceRepositories,
                r => r.PackageSource.Name,
                (r, t) => r.SearchAsync(searchText, filter, PageSize, t),
                LogError,
                cancellationToken);

            return(await WaitForCompletionOrBailOutAsync(searchText, searchTasks, cancellationToken));
        }
        internal async Task <IPackageSearchMetadata[]> GetMetadataForPackagesAndSortAsync <T>(T[] packages, bool includePrerelease, CancellationToken cancellationToken) where T : PackageIdentity
        {
            cancellationToken.ThrowIfCancellationRequested();

            IEnumerable <IPackageSearchMetadata> items = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => GetPackageMetadataAsync(p, includePrerelease, t),
                cancellationToken);

            // The packages were originally sorted which is important because we skip based on that sort
            // however, the asynchronous execution has randomly reordered the set. So, we need to resort.
            return(items.OrderBy(p => p.Identity.Id).ToArray());
        }
Пример #7
0
        public async Task <SearchResult <IPackageSearchMetadata> > SearchAsync(string searchText, SearchFilter filter, CancellationToken cancellationToken)
        {
            var searchOperationId = Guid.NewGuid();

            if (_telemetryService != null)
            {
                _telemetryService.EmitTelemetryEvent(new SearchTelemetryEvent(
                                                         searchOperationId,
                                                         searchText,
                                                         filter.IncludePrerelease));
            }

            SearchResult <IPackageSearchMetadata> result;

            using (var packageSourceTelemetry = new PackageSourceTelemetry(_sourceRepositories, searchOperationId, PackageSourceTelemetry.TelemetryAction.Search))
            {
                var searchTasks = TaskCombinators.ObserveErrorsAsync(
                    _sourceRepositories,
                    r => r.PackageSource.Name,
                    (r, t) => r.SearchAsync(searchText, filter, PageSize, t),
                    LogError,
                    cancellationToken);

                result = await WaitForCompletionOrBailOutAsync(
                    searchText,
                    searchTasks,
                    new TelemetryState(searchOperationId, pageIndex : 0),
                    cancellationToken);

                if (_telemetryService != null)
                {
                    await packageSourceTelemetry.SendTelemetryAsync();

                    var protocolDiagnosticTotals = packageSourceTelemetry.GetTotals();
                    _telemetryService.EmitTelemetryEvent(SourceTelemetry.GetSearchSourceSummaryEvent(
                                                             searchOperationId,
                                                             _sourceRepositories.Select(x => x.PackageSource),
                                                             protocolDiagnosticTotals));
                }
            }

            return(result);
        }
Пример #8
0
        public async Task <IEnumerable <IPackageSearchMetadata> > GetPackagesWithUpdatesAsync(string searchText, SearchFilter searchFilter, CancellationToken cancellationToken)
        {
            var packages = _installedPackages
                           .Where(p => !p.IsAutoReferenced())
                           .GetEarliest()
                           .Where(p => p.Id.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) != -1);

            // Prefetch metadata for all installed packages
            var prefetch = await TaskCombinators.ThrottledAsync(
                packages,
                (p, t) => _metadataProvider.GetPackageMetadataListAsync(p.Id, searchFilter.IncludePrerelease, includeUnlisted: false, cancellationToken: t),
                cancellationToken);

            // Flatten the result list
            var prefetchedPackages = prefetch
                                     .Where(p => p != null)
                                     .SelectMany(p => p)
                                     .ToArray();

            // Traverse all projects and determine packages with updates
            var packagesWithUpdates = new List <IPackageSearchMetadata>();

            foreach (var project in _projects)
            {
                var installed = await project.GetInstalledPackagesAsync(_serviceBroker, cancellationToken);

                foreach (var installedPackage in installed)
                {
                    var installedVersion = installedPackage.Identity.Version;
                    var allowedVersions  = installedPackage.AllowedVersions ?? VersionRange.All;

                    // filter packages based on current package identity
                    var allPackages = prefetchedPackages
                                      .Where(p => StringComparer.OrdinalIgnoreCase.Equals(
                                                 p.Identity.Id,
                                                 installedPackage.Identity.Id))
                                      .ToArray();

                    // and allowed versions
                    var allowedPackages = allPackages
                                          .Where(p => allowedVersions.Satisfies(p.Identity.Version));

                    // peek the highest available
                    var highest = allowedPackages
                                  .OrderByDescending(e => e.Identity.Version, VersionComparer.VersionRelease)
                                  .FirstOrDefault();

                    if (highest != null &&
                        VersionComparer.VersionRelease.Compare(installedVersion, highest.Identity.Version) < 0)
                    {
                        packagesWithUpdates.Add(highest.WithVersions(ToVersionInfo(allPackages)));
                    }
                }
            }

            // select the earliest package update candidates
            var uniquePackageIds = packagesWithUpdates
                                   .Select(p => p.Identity)
                                   .GetEarliest();

            // get unique list of package metadata as similar updates may come from different projects
            var uniquePackages = uniquePackageIds
                                 .GroupJoin(
                packagesWithUpdates,
                id => id,
                p => p.Identity,
                (id, pl) => pl.First());

            return(uniquePackages
                   .OrderBy(p => p.Identity.Id)
                   .ToArray());
        }