public PackageStatusOutdatedCheck( FeedPackageIdentity identity, DateTime commitTimestamp) { Identity = identity; Timestamp = commitTimestamp; }
public void UpdateFromExistingUpdatesExistingStatus(PackageState previousState, AccessCondition accessCondition, PackageState newState) { // Arrange var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6"); var existingStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult( feedPackageIdentity.Id, feedPackageIdentity.Version, PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(previousState)); existingStatus.AccessCondition = accessCondition; var newStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult( feedPackageIdentity.Id, feedPackageIdentity.Version, PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(newState)); // Act PackageMonitoringStatusAccessConditionHelper.UpdateFromExisting(newStatus, existingStatus); // Assert foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>()) { PackageMonitoringStatusTestUtility.AssertAccessCondition( state == previousState ? accessCondition : AccessCondition.GenerateIfNotExistsCondition(), newStatus.ExistingState[state]); } }
public PackageMonitoringStatus(FeedPackageIdentity package, PackageValidationResult validationResult, Exception validationException) : this() { Package = package; ValidationResult = validationResult; ValidationException = validationException; }
public async Task UpdateSavesNewStatus() { // Arrange var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6"); var packageValidationResult = new PackageValidationResult( new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)), null, null, Enumerable.Empty <AggregateValidationResult>()); var status = new PackageMonitoringStatus(packageValidationResult); var storageFactory = new MemoryStorageFactory(); var statusService = new PackageMonitoringStatusService( storageFactory, new Mock <ILogger <PackageMonitoringStatusService> >().Object); // Act await statusService.UpdateAsync(status, CancellationToken.None); // Assert Assert.True( storageFactory.Create( PackageState.Valid.ToString().ToLowerInvariant()) .Exists(GetPackageFileName(feedPackageIdentity.Id, feedPackageIdentity.Version))); }
private async Task <IEnumerable <CatalogIndexEntry> > FetchCatalogIndexEntriesFromRegistrationAsync( FeedPackageIdentity feedPackage, CancellationToken token) { var id = feedPackage.Id; var version = NuGetVersion.Parse(feedPackage.Version); var leafBlob = await _regResource.GetPackageMetadata( new PackageIdentity(id, version), NullSourceCacheContext.Instance, Logger.AsCommon(), token); if (leafBlob == null) { throw new Exception("Package is missing from registration!"); } var catalogPageUri = new Uri(leafBlob["@id"].ToString()); var catalogPage = await _client.GetJObjectAsync(catalogPageUri, token); return(new CatalogIndexEntry[] { new CatalogIndexEntry( catalogPageUri, Schema.DataTypes.PackageDetails.ToString(), catalogPage["catalog:commitId"].ToString(), DateTime.Parse(catalogPage["catalog:commitTimeStamp"].ToString()), id, version) }); }
public async Task <PackageMonitoringStatus> GetAsync(FeedPackageIdentity package, CancellationToken token) { var statusTasks = _packageStateNames .Select(state => GetPackageAsync(GetStorage(state), package, token)) .ToList(); var statuses = (await Task.WhenAll(statusTasks)) .Where(s => s != null); if (!statuses.Any()) { return(null); } // If more than one status exist for a single package, find the status with the latest timestamp. var statusesWithTimeStamps = statuses.Where(s => s.ValidationResult != null && s.ValidationResult.CatalogEntries != null && s.ValidationResult.CatalogEntries.Any()); if (statusesWithTimeStamps.Any()) { return(statusesWithTimeStamps.OrderByDescending(s => s.ValidationResult.CatalogEntries.Max(c => c.CommitTimeStamp)).First()); } else { // No statuses have timestamps (they all failed to process). // Because they are all in a bad state, choose an arbitrary one. return(statuses.First()); } }
public async Task GetByPackageDeletesOutdatedStatuses(PackageState latest, PackageState outdated) { // Arrange var storageFactory = new MemoryStorageFactory(); var statusService = new PackageMonitoringStatusService( storageFactory, new Mock <ILogger <PackageMonitoringStatusService> >().Object); var id = "howdyFriend"; var version = "5.5.5"; var package = new FeedPackageIdentity(id, version); var outdatedStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult( id, version, PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(latest), new DateTime(2019, 6, 10)); var latestStatus = PackageMonitoringStatusTestUtility.CreateStatusWithPackageValidationResult( id, version, PackageMonitoringStatusTestUtility.GetTestResultFromPackageState(outdated), new DateTime(2019, 6, 11)); await SaveToStorage(storageFactory, outdatedStatus); await SaveToStorage(storageFactory, latestStatus); // Act var status = await statusService.GetAsync(package, CancellationToken.None); // Assert PackageMonitoringStatusTestUtility.AssertStatus(latestStatus, status); Assert.Equal(latest == outdated, DoesPackageExists(storageFactory, outdatedStatus.State, package)); Assert.True(DoesPackageExists(storageFactory, latestStatus.State, package)); }
private string GetPackageFileName(FeedPackageIdentity package) { var idString = package.Id.ToLowerInvariant(); var versionString = package.Version.ToLowerInvariant(); return($"{idString}/" + $"{idString}.{versionString}.json"); }
public void FeedPackageIdentityEquals(string idA, string versionA, string idB, string versionB, bool success) { var packageA = new FeedPackageIdentity(idA, versionA); var packageB = new FeedPackageIdentity(idB, versionB); Assert.Equal(success, packageA.Equals(packageB)); Assert.Equal(success, packageB.Equals(packageA)); Assert.Equal(success, packageA.GetHashCode() == packageB.GetHashCode()); }
private async Task DeleteAsync(FeedPackageIdentity package, PackageState state, CancellationToken token) { var storage = GetStorage(state); if (!storage.Exists(GetPackageFileName(package))) { return; } await storage.DeleteAsync(GetPackageUri(storage, package), token); }
private async Task SaveFailedPackageMonitoringStatusAsync( PackageValidatorContext queuedContext, Exception exception, CancellationToken token) { var feedPackage = new FeedPackageIdentity(queuedContext.Package.Id, queuedContext.Package.Version); await _notificationService.OnPackageValidationFailedAsync(feedPackage.Id, feedPackage.Version, exception, token); var status = new PackageMonitoringStatus(feedPackage, exception); await _statusService.UpdateAsync(status, token); }
public async Task UpdateDeletesOldStatuses(PackageState?previousState) { // Arrange var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6"); var packageValidationResult = new PackageValidationResult( new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)), null, null, Enumerable.Empty <AggregateValidationResult>()); var status = new PackageMonitoringStatus(packageValidationResult); var storageFactory = new MemoryStorageFactory(); var statusService = new PackageMonitoringStatusService( storageFactory, new Mock <ILogger <PackageMonitoringStatusService> >().Object); var etag = "theETag"; foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>()) { if (previousState != state) { status.ExistingState[state] = AccessCondition.GenerateIfNotExistsCondition(); continue; } var content = new StringStorageContentWithETag("{}", etag); await SaveToStorage(storageFactory, state, feedPackageIdentity, content); status.ExistingState[state] = AccessCondition.GenerateIfMatchCondition(etag); } // Act await statusService.UpdateAsync(status, CancellationToken.None); // Assert foreach (var state in Enum.GetValues(typeof(PackageState)).Cast <PackageState>()) { Assert.Equal( state == status.State, DoesPackageExists(storageFactory, state, feedPackageIdentity)); } PackageMonitoringStatusTestUtility.AssertStatus( status, await statusService.GetAsync(feedPackageIdentity, CancellationToken.None)); }
private async Task DeleteAsync(FeedPackageIdentity package, PackageState state, AccessCondition accessCondition, CancellationToken token) { var storage = GetStorage(state); if (!storage.Exists(GetPackageFileName(package))) { return; } await storage.DeleteAsync( GetPackageUri(storage, package), token, new DeleteRequestOptionsWithAccessCondition( accessCondition)); }
private async Task SaveFailedPackageMonitoringStatusAsync( PackageValidatorContext queuedContext, Exception exception, CancellationToken token) { var queuedVersion = queuedContext.Package.Version; var version = NuGetVersion.TryParse(queuedVersion, out var parsedVersion) ? parsedVersion.ToFullString() : queuedVersion; var feedPackage = new FeedPackageIdentity(queuedContext.Package.Id, version); await _notificationService.OnPackageValidationFailedAsync(feedPackage.Id, feedPackage.Version, exception, token); var status = new PackageMonitoringStatus(feedPackage, exception); await _statusService.UpdateAsync(status, token); }
protected override async Task ProcessSortedBatchAsync(CollectorHttpClient client, KeyValuePair <FeedPackageIdentity, IList <JObject> > sortedBatch, JToken context, CancellationToken cancellationToken) { var packageId = sortedBatch.Key.Id; var packageVersion = sortedBatch.Key.Version; var feedPackage = new FeedPackageIdentity(packageId, packageVersion); _logger.LogInformation("Processing catalog entries for {PackageId} {PackageVersion}.", packageId, packageVersion); var catalogEntries = sortedBatch.Value.Select(c => new CatalogIndexEntry(c)); _logger.LogInformation("Adding {MostRecentCatalogEntryUri} to queue.", catalogEntries.OrderByDescending(c => c.CommitTimeStamp).First().Uri); await _queue.AddAsync( new PackageValidatorContext(feedPackage, catalogEntries), cancellationToken); }
public async Task UpdateDeletesOldStatuses() { // Arrange var feedPackageIdentity = new FeedPackageIdentity("howdy", "3.4.6"); var packageFileName = GetPackageFileName(feedPackageIdentity.Id, feedPackageIdentity.Version); var packageValidationResult = new PackageValidationResult( new PackageIdentity(feedPackageIdentity.Id, new NuGetVersion(feedPackageIdentity.Version)), null, null, Enumerable.Empty <AggregateValidationResult>()); var status = new PackageMonitoringStatus(packageValidationResult); var storageFactory = new MemoryStorageFactory(); var statusService = new PackageMonitoringStatusService( storageFactory, new Mock <ILogger <PackageMonitoringStatusService> >().Object); foreach (var state in Enum.GetNames(typeof(PackageState))) { var storage = storageFactory.Create(state.ToLowerInvariant()); await storage.SaveAsync(storage.ResolveUri(packageFileName), new StringStorageContent("{}"), CancellationToken.None); Assert.True(storage.Exists(packageFileName)); } // Act await statusService.UpdateAsync(status, CancellationToken.None); // Assert foreach (var state in Enum.GetNames(typeof(PackageState))) { var storage = storageFactory.Create(state.ToLowerInvariant()); if ((PackageState)Enum.Parse(typeof(PackageState), state) == status.State) { Assert.True(storage.Exists(packageFileName)); } else { Assert.False(storage.Exists(packageFileName)); } } AssertStatus(status, await statusService.GetAsync(feedPackageIdentity, CancellationToken.None)); }
public void PackageIdentityConstructorUsesFullString() { const string id = "id"; const string versionString = "1.0.0+buildmetadata"; var package = new PackageIdentity(id, NuGetVersion.Parse(versionString)); var feedPackage = new FeedPackageIdentity(package); var equivalentFeedPackage1 = new FeedPackageIdentity(id, versionString); var equivalentFeedPackage2 = new FeedPackageIdentity(package.Id, package.Version.ToFullString()); var differentFeedPackage = new FeedPackageIdentity(package.Id, package.Version.ToNormalizedString()); foreach (var equivalentFeedPackage in new FeedPackageIdentity[] { equivalentFeedPackage1, equivalentFeedPackage2 }) { Assert.True(feedPackage.Equals(equivalentFeedPackage)); Assert.Equal(feedPackage.GetHashCode(), equivalentFeedPackage.GetHashCode()); } Assert.False(feedPackage.Equals(differentFeedPackage)); Assert.NotEqual(feedPackage.GetHashCode(), differentFeedPackage.GetHashCode()); }
public async Task <PackageMonitoringStatus> GetAsync(FeedPackageIdentity package, CancellationToken token) { var statusTasks = _packageStateNames .Select(state => GetPackageAsync(GetStorage(state), package, token)) .ToList(); var statuses = (await Task.WhenAll(statusTasks)) .Where(s => s != null); if (!statuses.Any()) { return(null); } // If more than one status exist for a single package, find the status with the latest timestamp. // We then must delete the other statuses, so that we can later update the storage safely. var statusesWithTimeStamps = statuses.Where(s => s.ValidationResult != null && s.ValidationResult.CatalogEntries != null && s.ValidationResult.CatalogEntries.Any()); IEnumerable <PackageMonitoringStatus> orderedStatuses; if (statusesWithTimeStamps.Any()) { orderedStatuses = statusesWithTimeStamps.OrderByDescending(s => s.ValidationResult.CatalogEntries.Max(c => c.CommitTimeStamp)); } else { // No statuses have timestamps (they all failed to process). // Because they are all in a bad state, choose an arbitrary one. orderedStatuses = statuses; } var result = orderedStatuses.First(); foreach (var statusToDelete in orderedStatuses.Skip(1)) { await DeleteAsync(statusToDelete.Package, statusToDelete.State, statusToDelete.AccessCondition, token); } return(result); }
private bool DoesPackageExists(MemoryStorageFactory storageFactory, PackageState state, FeedPackageIdentity package) { var stateName = Enum.GetName(typeof(PackageState), state); var storage = storageFactory.Create(stateName.ToLowerInvariant()); var packageFileName = GetPackageFileName(package.Id, package.Version); return(storage.Exists(packageFileName)); }
public PackageValidatorContext(FeedPackageIdentity package, IEnumerable <CatalogIndexEntry> catalogEntries) { Package = package ?? throw new ArgumentNullException(nameof(package)); CatalogEntries = catalogEntries ?? throw new ArgumentNullException(nameof(catalogEntries)); }
private Task <PackageMonitoringStatus> GetPackageAsync(CatalogStorage storage, FeedPackageIdentity package, CancellationToken token) { return(GetPackageAsync(storage, GetPackageFileName(package), token)); }
public PackageMonitoringStatus(PackageValidationResult result) { ValidationResult = result ?? throw new ArgumentNullException(nameof(result)); Package = new FeedPackageIdentity(result.Package); }
private Uri GetPackageUri(CatalogStorage storage, FeedPackageIdentity package) { return(storage.ResolveUri(GetPackageFileName(package))); }
public PackageMonitoringStatus(FeedPackageIdentity package, Exception exception) { Package = package ?? throw new ArgumentNullException(nameof(package)); ValidationException = exception ?? throw new ArgumentNullException(nameof(exception)); }
public PackageMonitoringStatusListItem(FeedPackageIdentity package, PackageState state) { Package = package; State = state; }
public PackageValidatorContext(FeedPackageIdentity package, IEnumerable <CatalogIndexEntry> catalogEntries) { Package = package; CatalogEntries = catalogEntries; }
private Task SaveToStorage(MemoryStorageFactory storageFactory, PackageState state, FeedPackageIdentity package, StorageContent content) { var stateName = Enum.GetName(typeof(PackageState), state); var storage = storageFactory.Create(stateName.ToLowerInvariant()); var packageFileName = GetPackageFileName(package.Id, package.Version); return(storage.SaveAsync(storage.ResolveUri(packageFileName), content, CancellationToken.None)); }