Example #1
0
        public async Task UpdateMetadataAsync(Package entity, object metadata, bool commitChanges = true)
        {
            PackageStreamMetadata typedMetadata = metadata == null ? null : metadata as PackageStreamMetadata;

            if (typedMetadata != null)
            {
                if (typedMetadata.Size != entity.PackageFileSize ||
                    typedMetadata.Hash != entity.Hash ||
                    typedMetadata.HashAlgorithm != entity.HashAlgorithm)
                {
                    await _galleryEntityService.UpdatePackageStreamMetadataAsync(entity, typedMetadata, commitChanges);
                }
            }
        }
        private async Task <PackageStatus> MarkPackageAsAvailableAsync(PackageValidationSet validationSet, Package package, bool copied)
        {
            // Use whatever package made it into the packages container. This is what customers will consume so the DB
            // record must match.
            using (var packageStream = await _packageFileService.DownloadPackageFileToDiskAsync(package))
            {
                var stopwatch = Stopwatch.StartNew();
                var hash      = CryptographyService.GenerateHash(packageStream, CoreConstants.Sha512HashAlgorithmId);
                _telemetryService.TrackDurationToHashPackage(
                    stopwatch.Elapsed,
                    package.PackageRegistration.Id,
                    package.NormalizedVersion,
                    CoreConstants.Sha512HashAlgorithmId,
                    packageStream.GetType().FullName);

                var streamMetadata = new PackageStreamMetadata
                {
                    Size          = packageStream.Length,
                    Hash          = hash,
                    HashAlgorithm = CoreConstants.Sha512HashAlgorithmId,
                };

                // We don't immediately commit here. Later, we will commit these changes as well as the new package
                // status as part of the same transaction.
                if (streamMetadata.Size != package.PackageFileSize ||
                    streamMetadata.Hash != package.Hash ||
                    streamMetadata.HashAlgorithm != package.HashAlgorithm)
                {
                    await _galleryPackageService.UpdatePackageStreamMetadataAsync(
                        package,
                        streamMetadata,
                        commitChanges : false);
                }
            }

            _logger.LogInformation("Marking package {PackageId} {PackageVersion}, validation set {ValidationSetId} as {PackageStatus} in DB",
                                   package.PackageRegistration.Id,
                                   package.NormalizedVersion,
                                   validationSet.ValidationTrackingId,
                                   PackageStatus.Available);

            var fromStatus = package.PackageStatusKey;

            try
            {
                // Make the package available and commit any other pending changes (e.g. updated hash).
                await _galleryPackageService.UpdatePackageStatusAsync(package, PackageStatus.Available, commitChanges : true);
            }
            catch (Exception e)
            {
                _logger.LogError(
                    Error.UpdatingPackageDbStatusFailed,
                    e,
                    "Failed to update package status in Gallery Db. Package {PackageId} {PackageVersion}, validation set {ValidationSetId}",
                    package.PackageRegistration.Id,
                    package.NormalizedVersion,
                    validationSet.ValidationTrackingId);

                // If this execution was not the one to copy the package, then don't delete the package on failure.
                // This prevents a missing passing in the (unlikely) case where two actors attempt the DB update, one
                // succeeds and one fails. We don't want an available package record with nothing in the packages
                // container!
                if (copied && fromStatus != PackageStatus.Available)
                {
                    await _packageFileService.DeletePackageFileAsync(package.PackageRegistration.Id, package.Version);
                }

                throw;
            }

            return(fromStatus);
        }