Skip to content
This repository was archived by the owner on Jul 30, 2024. It is now read-only.

Commit 3e45ecf

Browse files
committed
Back up the package if there are any processors (#374)
Progress on NuGet/Engineering#1190
1 parent 09e4219 commit 3e45ecf

6 files changed

Lines changed: 177 additions & 20 deletions

File tree

src/NuGet.Services.Validation.Orchestrator/IValidationPackageFileService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ public interface IValidationPackageFileService : ICorePackageFileService
1717
/// <returns>The package stream.</returns>
1818
Task<Stream> DownloadPackageFileToDiskAsync(Package package);
1919

20+
/// <summary>
21+
/// Backs up the package file from the location specific for the validation set.
22+
/// </summary>
23+
/// <param name="package">The package metadata.</param>
24+
/// <param name="validationSet">The validation set, containing validation set and package identifiers.</param>
25+
Task BackupPackageFileFromValidationSetPackageAsync(Package package, PackageValidationSet validationSet);
26+
2027
/// <summary>
2128
/// Copy a package from the validation container to a location specific for the validation set. This allows the
2229
/// validation set to have its own copy of the package to mutate (via <see cref="IProcessor"/>) and validate.

src/NuGet.Services.Validation.Orchestrator/ValidationPackageFileService.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ namespace NuGet.Services.Validation.Orchestrator
1313
{
1414
public class ValidationPackageFileService : CorePackageFileService, IValidationPackageFileService
1515
{
16+
/// <summary>
17+
/// The value picked today is based off of the maximum duration we wait when downloading packages using the
18+
/// <see cref="IPackageDownloader"/>.
19+
/// </summary>
20+
private static readonly TimeSpan AccessDuration = TimeSpan.FromMinutes(10);
21+
1622
private readonly ICoreFileStorageService _fileStorageService;
1723
private readonly IPackageDownloader _packageDownloader;
1824
private readonly ILogger<ValidationPackageFileService> _logger;
@@ -50,6 +56,24 @@ public Task CopyValidationPackageForValidationSetAsync(PackageValidationSet vali
5056
AccessConditionWrapper.GenerateEmptyCondition());
5157
}
5258

59+
public async Task BackupPackageFileFromValidationSetPackageAsync(Package package, PackageValidationSet validationSet)
60+
{
61+
_logger.LogInformation(
62+
"Backing up package for validation set {ValidationTrackingId} ({PackageId} {PackageVersion}).",
63+
validationSet.ValidationTrackingId,
64+
validationSet.PackageId,
65+
validationSet.PackageNormalizedVersion);
66+
67+
var packageUri = await GetPackageForValidationSetReadUriAsync(
68+
validationSet,
69+
DateTimeOffset.UtcNow.Add(AccessDuration));
70+
71+
using (var packageStream = await _packageDownloader.DownloadAsync(packageUri, CancellationToken.None))
72+
{
73+
await StorePackageFileInBackupLocationAsync(package, packageStream);
74+
}
75+
}
76+
5377
public Task<string> CopyPackageFileForValidationSetAsync(PackageValidationSet validationSet)
5478
{
5579
var srcFileName = BuildFileName(

src/NuGet.Services.Validation.Orchestrator/ValidationSetProvider.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using System.Threading.Tasks;
78
using Microsoft.Extensions.Logging;
89
using Microsoft.Extensions.Options;
@@ -15,19 +16,22 @@ public class ValidationSetProvider : IValidationSetProvider
1516
{
1617
private readonly IValidationStorageService _validationStorageService;
1718
private readonly IValidationPackageFileService _packageFileService;
19+
private readonly IValidatorProvider _validatorProvider;
1820
private readonly ValidationConfiguration _validationConfiguration;
1921
private readonly ITelemetryService _telemetryService;
2022
private readonly ILogger<ValidationSetProvider> _logger;
2123

2224
public ValidationSetProvider(
2325
IValidationStorageService validationStorageService,
2426
IValidationPackageFileService packageFileService,
27+
IValidatorProvider validatorProvider,
2528
IOptionsSnapshot<ValidationConfiguration> validationConfigurationAccessor,
2629
ITelemetryService telemetryService,
2730
ILogger<ValidationSetProvider> logger)
2831
{
2932
_validationStorageService = validationStorageService ?? throw new ArgumentNullException(nameof(validationStorageService));
3033
_packageFileService = packageFileService ?? throw new ArgumentNullException(nameof(packageFileService));
34+
_validatorProvider = validatorProvider ?? throw new ArgumentNullException(nameof(validatorProvider));
3135
if (validationConfigurationAccessor == null)
3236
{
3337
throw new ArgumentNullException(nameof(validationConfigurationAccessor));
@@ -70,6 +74,13 @@ public async Task<PackageValidationSet> TryGetOrCreateValidationSetAsync(Guid va
7074
validationSet.PackageETag = null;
7175
}
7276

77+
// If there are any processors in the validation set, back up the original. We back up from the
78+
// validation set copy to avoid concurrency issues.
79+
if (validationSet.PackageValidations.Any(x => _validatorProvider.IsProcessor(x.Type)))
80+
{
81+
await _packageFileService.BackupPackageFileFromValidationSetPackageAsync(package, validationSet);
82+
}
83+
7384
validationSet = await PersistValidationSetAsync(validationSet, package);
7485
}
7586
else

src/Validation.Common.Job/Validation.Common.Job.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
<Version>2.18.0</Version>
8585
</PackageReference>
8686
<PackageReference Include="NuGetGallery.Core">
87-
<Version>4.4.4-dev-25804</Version>
87+
<Version>4.4.4-dev-25969</Version>
8888
</PackageReference>
8989
<PackageReference Include="Serilog">
9090
<Version>2.5.0</Version>

tests/NuGet.Services.Validation.Orchestrator.Tests/ValidationPackageFileServiceFacts.cs

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.IO;
6+
using System.Text;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using Microsoft.Extensions.Logging;
@@ -18,11 +19,16 @@ public class ValidationPackageFileServiceFacts
1819
private readonly PackageValidationSet _validationSet;
1920
private readonly Package _package;
2021
private readonly string _validationContainerName;
22+
private readonly string _backupContainerName;
2123
private readonly string _packagesContainerName;
2224
private readonly string _packageFileName;
2325
private readonly string _validationSetPackageFileName;
26+
private readonly string _backupFileName;
2427
private readonly Uri _testUri;
2528
private readonly string _etag;
29+
private readonly string _packageContent;
30+
private readonly MemoryStream _packageStream;
31+
private readonly DateTimeOffset _endOfAccess;
2632
private readonly Mock<ICoreFileStorageService> _fileStorageService;
2733
private readonly Mock<IPackageDownloader> _packageDownloader;
2834
private readonly Mock<ILogger<ValidationPackageFileService>> _logger;
@@ -37,6 +43,7 @@ public ValidationPackageFileServiceFacts()
3743
Id = "NuGet.Versioning",
3844
},
3945
NormalizedVersion = "4.5.0-ALPHA",
46+
Hash = "NzMzMS1QNENLNEczSDQ1SA==",
4047
};
4148
_validationSet = new PackageValidationSet
4249
{
@@ -47,10 +54,15 @@ public ValidationPackageFileServiceFacts()
4754

4855
_packagesContainerName = "packages";
4956
_validationContainerName = "validation";
57+
_backupContainerName = "package-backups";
5058
_packageFileName = "nuget.versioning.4.5.0-alpha.nupkg";
5159
_validationSetPackageFileName = "validation-sets/0b44d53f-0689-4f82-9530-f25f26b321aa/nuget.versioning.4.5.0-alpha.nupkg";
60+
_backupFileName = "nuget.versioning/4.5.0-alpha/rQw3wx1psxXzqB8TyM3nAQlK2RcluhsNwxmcqXE2YbgoDW735o8TPmIR4uWpoxUERddvFwjgRSGw7gNPCwuvJg2..nupkg";
5261
_testUri = new Uri("http://example.com/nupkg.nupkg");
5362
_etag = "\"some-etag\"";
63+
_packageContent = "Hello, world.";
64+
_packageStream = new MemoryStream(Encoding.ASCII.GetBytes(_packageContent));
65+
_endOfAccess = new DateTimeOffset(2018, 1, 3, 8, 30, 0, TimeSpan.Zero);
5466

5567
_fileStorageService = new Mock<ICoreFileStorageService>(MockBehavior.Strict);
5668
_packageDownloader = new Mock<IPackageDownloader>(MockBehavior.Strict);
@@ -62,6 +74,45 @@ public ValidationPackageFileServiceFacts()
6274
_logger.Object);
6375
}
6476

77+
[Fact]
78+
public async Task BackupPackageFileFromValidationSetPackageAsync()
79+
{
80+
DateTimeOffset? endOfAccess = null;
81+
_fileStorageService
82+
.Setup(x => x.GetFileReadUriAsync(
83+
_validationContainerName,
84+
_validationSetPackageFileName,
85+
It.IsAny<DateTimeOffset?>()))
86+
.ReturnsAsync(_testUri)
87+
.Callback<string, string, DateTimeOffset?>((_, __, a) => endOfAccess = a)
88+
.Verifiable();
89+
90+
_packageDownloader
91+
.Setup(x => x.DownloadAsync(_testUri, CancellationToken.None))
92+
.ReturnsAsync(_packageStream)
93+
.Verifiable();
94+
95+
_fileStorageService
96+
.Setup(x => x.FileExistsAsync(_backupContainerName, _backupFileName))
97+
.ReturnsAsync(false)
98+
.Verifiable();
99+
100+
_fileStorageService
101+
.Setup(x => x.SaveFileAsync(_backupContainerName, _backupFileName, _packageStream, true))
102+
.Returns(Task.CompletedTask)
103+
.Verifiable();
104+
105+
var before = DateTimeOffset.UtcNow;
106+
await _target.BackupPackageFileFromValidationSetPackageAsync(_package, _validationSet);
107+
var after = DateTimeOffset.UtcNow;
108+
109+
_fileStorageService.Verify();
110+
_packageDownloader.Verify();
111+
Assert.NotNull(endOfAccess);
112+
Assert.InRange(endOfAccess.Value, before.AddMinutes(10), after.AddMinutes(10));
113+
Assert.Throws<ObjectDisposedException>(() => _packageStream.Length);
114+
}
115+
65116
[Fact]
66117
public async Task DownloadPackageFileToDiskAsync()
67118
{
@@ -72,18 +123,17 @@ public async Task DownloadPackageFileToDiskAsync()
72123
null))
73124
.ReturnsAsync(_testUri)
74125
.Verifiable();
75-
76-
var expected = new MemoryStream();
126+
77127
_packageDownloader
78-
.Setup(x => x.DownloadAsync(
79-
_testUri,
80-
CancellationToken.None))
81-
.ReturnsAsync(expected);
128+
.Setup(x => x.DownloadAsync(_testUri, CancellationToken.None))
129+
.ReturnsAsync(_packageStream)
130+
.Verifiable();
82131

83132
var actual = await _target.DownloadPackageFileToDiskAsync(_package);
84133

85-
Assert.Same(expected, actual);
134+
Assert.Same(_packageStream, actual);
86135
_fileStorageService.Verify();
136+
_packageDownloader.Verify();
87137
}
88138

89139
[Fact]
@@ -96,7 +146,7 @@ public async Task CopyValidationPackageForValidationSetAsync()
96146
_validationContainerName,
97147
_validationSetPackageFileName,
98148
It.Is<IAccessCondition>(y => y.IfMatchETag == null && y.IfNoneMatchETag == null)))
99-
.ReturnsAsync(string.Empty)
149+
.ReturnsAsync(_etag)
100150
.Verifiable();
101151

102152
await _target.CopyValidationPackageForValidationSetAsync(_validationSet);
@@ -133,7 +183,7 @@ public async Task CopyValidationPackageToPackageFileAsync()
133183
_packagesContainerName,
134184
_packageFileName,
135185
It.Is<IAccessCondition>(y => y.IfNoneMatchETag == "*")))
136-
.ReturnsAsync(string.Empty)
186+
.ReturnsAsync(_etag)
137187
.Verifiable();
138188

139189
await _target.CopyValidationPackageToPackageFileAsync(_validationSet.PackageId, _validationSet.PackageNormalizedVersion);
@@ -168,7 +218,7 @@ public async Task CopyValidationSetPackageToPackageFileAsync()
168218
_packagesContainerName,
169219
_packageFileName,
170220
accessCondition))
171-
.ReturnsAsync(string.Empty)
221+
.ReturnsAsync(_etag)
172222
.Verifiable();
173223

174224
await _target.CopyValidationSetPackageToPackageFileAsync(_validationSet, accessCondition);
@@ -211,16 +261,15 @@ public async Task DeletePackageForValidationSetAsync()
211261
[Fact]
212262
public async Task GetPackageForValidationSetReadUriAsync()
213263
{
214-
var endOfAccess = new DateTimeOffset(2018, 1, 3, 8, 30, 0, TimeSpan.Zero);
215264
_fileStorageService
216265
.Setup(x => x.GetFileReadUriAsync(
217266
_validationContainerName,
218267
_validationSetPackageFileName,
219-
endOfAccess))
268+
_endOfAccess))
220269
.ReturnsAsync(_testUri)
221270
.Verifiable();
222271

223-
var actual = await _target.GetPackageForValidationSetReadUriAsync(_validationSet, endOfAccess);
272+
var actual = await _target.GetPackageForValidationSetReadUriAsync(_validationSet, _endOfAccess);
224273

225274
Assert.Equal(_testUri, actual);
226275
_fileStorageService.Verify();

0 commit comments

Comments
 (0)