Пример #1
0
        public async Task UpdateAsync(
            HiveType hive,
            IReadOnlyList <HiveType> replicaHives,
            string id,
            IReadOnlyList <CatalogCommitItem> entries,
            IReadOnlyDictionary <CatalogCommitItem, PackageDetailsCatalogLeaf> entryToCatalogLeaf,
            CatalogCommit registrationCommit)
        {
            // Validate the input and put it in more convenient forms.
            if (!entries.Any())
            {
                return;
            }
            GuardInput(entries, entryToCatalogLeaf);
            var sortedCatalog        = entries.OrderBy(x => x.PackageIdentity.Version).ToList();
            var versionToCatalogLeaf = entryToCatalogLeaf.ToDictionary(x => x.Key.PackageIdentity.Version, x => x.Value);

            // Remove SemVer 2.0.0 versions if this hive should only have SemVer 1.0.0 versions.
            if (ShouldExcludeSemVer2(hive))
            {
                Guard.Assert(
                    replicaHives.All(ShouldExcludeSemVer2),
                    "A replica hive of a non-SemVer 2.0.0 hive must also exclude SemVer 2.0.0.");

                ExcludeSemVer2(hive, sortedCatalog, versionToCatalogLeaf);
            }
            else
            {
                Guard.Assert(
                    replicaHives.All(x => !ShouldExcludeSemVer2(x)),
                    "A replica hive of a SemVer 2.0.0 hive must also include SemVer 2.0.0.");
            }

            _logger.LogInformation(
                "Starting to update the {PackageId} registration index in the {Hive} hive and {ReplicaHives} replica hives with {UpsertCount} " +
                "package details and {DeleteCount} package deletes.",
                id,
                hive,
                replicaHives,
                entryToCatalogLeaf.Count,
                entries.Count - entryToCatalogLeaf.Count);

            // Read the existing registration index if it exists. If it does not exist, initialize a new index.
            var index = await _storage.ReadIndexOrNullAsync(hive, id);

            IndexInfo indexInfo;

            if (index == null)
            {
                indexInfo = IndexInfo.New();
            }
            else
            {
                indexInfo = IndexInfo.Existing(_storage, hive, index);
            }

            // Find all of the existing page URLs. This will be used later to find orphan pages.
            var existingPageUrls = GetPageUrls(indexInfo);

            // Read all of the obviously relevant pages in parallel. This simply evaluates some work that would
            // otherwise be done lazily.
            await LoadRelevantPagesAsync(sortedCatalog, indexInfo);

            // Merge the incoming catalog entries in memory.
            var mergeResult = await _merger.MergeAsync(indexInfo, sortedCatalog);

            // Write the modified leaves.
            await UpdateLeavesAsync(hive, replicaHives, id, versionToCatalogLeaf, registrationCommit, mergeResult);

            // Write the pages and handle the inline vs. non-inlined cases.
            if (indexInfo.Items.Count == 0)
            {
                _logger.LogInformation("There are no pages to update.");
            }
            else
            {
                var itemCount = indexInfo.Items.Sum(x => x.Count);
                if (itemCount <= _options.Value.MaxInlinedLeafItems)
                {
                    _logger.LogInformation(
                        "There are {Count} total leaf items so the leaf items will be inlined.",
                        itemCount);

                    await UpdateInlinedPagesAsync(hive, id, indexInfo, registrationCommit);
                }
                else
                {
                    _logger.LogInformation(
                        "There are {Count} total leaf items so the leaf items will not be inlined.",
                        itemCount);

                    await UpdateNonInlinedPagesAsync(hive, replicaHives, id, indexInfo, registrationCommit, mergeResult);
                }
            }

            // Write the index, if there were any changes.
            if (mergeResult.ModifiedPages.Any() || mergeResult.ModifiedLeaves.Any())
            {
                _logger.LogInformation("Updating the index.");
                _entityBuilder.UpdateIndex(indexInfo.Index, hive, id, indexInfo.Items.Count);
                _entityBuilder.UpdateCommit(indexInfo.Index, registrationCommit);
                await _storage.WriteIndexAsync(hive, replicaHives, id, indexInfo.Index);
            }

            if (!indexInfo.Items.Any())
            {
                _logger.LogInformation("Deleting the index since there are no more page items.");
                await _storage.DeleteIndexAsync(hive, replicaHives, id);
            }

            // Delete orphan blobs.
            await DeleteOrphansAsync(hive, replicaHives, existingPageUrls, indexInfo, mergeResult);

            _logger.LogInformation(
                "Done updating the {PackageId} registration index in the {Hive} hive and replica hives {ReplicaHives}. {ModifiedPages} pages were " +
                "updated, {ModifiedLeaves} leaves were upserted, and {DeletedLeaves} leaves were deleted.",
                id,
                hive,
                replicaHives,
                mergeResult.ModifiedPages.Count,
                mergeResult.ModifiedLeaves.Count,
                mergeResult.DeletedLeaves.Count);
        }