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); }