Esempio n. 1
0
        private async Task <StartRevalidationResult> StartRevalidationsAsync(IReadOnlyList <PackageRevalidation> revalidations)
        {
            _logger.LogInformation("Starting {RevalidationCount} revalidations...", revalidations.Count);

            foreach (var revalidation in revalidations)
            {
                _logger.LogInformation(
                    "Starting revalidation for package {PackageId} {PackageVersion}...",
                    revalidation.PackageId,
                    revalidation.PackageNormalizedVersion);

                var message = PackageValidationMessageData.NewProcessValidationSet(
                    revalidation.PackageId,
                    revalidation.PackageNormalizedVersion,
                    revalidation.ValidationTrackingId.Value,
                    ValidatingType.Package,
                    entityKey: null);

                await _validationEnqueuer.SendMessageAsync(message);

                _telemetryService.TrackPackageRevalidationStarted(revalidation.PackageId, revalidation.PackageNormalizedVersion);
                _logger.LogInformation(
                    "Started revalidation for package {PackageId} {PackageVersion}",
                    revalidation.PackageId,
                    revalidation.PackageNormalizedVersion);
            }

            _logger.LogInformation("Started {RevalidationCount} revalidations, marking them as enqueued...", revalidations.Count);

            await _packageState.MarkPackageRevalidationsAsEnqueuedAsync(revalidations);

            _logger.LogInformation("Marked {RevalidationCount} revalidations as enqueued", revalidations.Count);

            return(StartRevalidationResult.RevalidationsEnqueued(revalidations.Count));
        }
        public async Task <PackageStatus> StartValidationAsync(TPackageEntity package)
        {
            var validatingType = ValidateAndGetType(package);

            var entityKey = package.Key == default(int) ? (int?)null : package.Key;
            var data      = PackageValidationMessageData.NewProcessValidationSet(
                package.Id,
                package.Version,
                Guid.NewGuid(),
                validatingType,
                entityKey: entityKey);

            var activityName = $"Enqueuing asynchronous package validation: " +
                               $"{data.ProcessValidationSet.PackageId} {data.ProcessValidationSet.PackageVersion} " +
                               $"{data.ProcessValidationSet.ValidatingType} ({data.ProcessValidationSet.ValidationTrackingId})";

            using (_diagnosticsSource.Activity(activityName))
            {
                var postponeProcessingTill = DateTimeOffset.UtcNow + _appConfiguration.AsynchronousPackageValidationDelay;

                await _validationEnqueuer.SendMessageAsync(data, postponeProcessingTill);
            }

            return(TargetPackageStatus);
        }
        private async Task ScheduleCheckIfNotTimedOut(
            PackageValidationSet validationSet,
            IValidatingEntity <T> validatingEntity,
            bool scheduleNextCheck,
            bool tooLongNotificationAllowed)
        {
            var validationSetDuration = await UpdateValidationDurationAsync(validationSet, validatingEntity, tooLongNotificationAllowed);

            // Schedule another check if we haven't reached the validation set timeout yet.
            if (validationSetDuration <= _validationConfiguration.TimeoutValidationSetAfter)
            {
                if (scheduleNextCheck)
                {
                    var messageData = PackageValidationMessageData.NewProcessValidationSet(
                        validationSet.PackageId,
                        validationSet.PackageNormalizedVersion,
                        validationSet.ValidationTrackingId,
                        validationSet.ValidatingType,
                        entityKey: validationSet.PackageKey);
                    var postponeUntil = DateTimeOffset.UtcNow + _validationConfiguration.ValidationMessageRecheckPeriod;

                    await _validationEnqueuer.SendMessageAsync(messageData, postponeUntil);
                }
            }
            else
            {
                _logger.LogWarning("Abandoning checking status of validation set {ValidationTrackingId} for " +
                                   "package {PackageId} {PackageVersion} because it took too long (Duration: {Duration}, CutOffDuration: {CutOffDuration})",
                                   validationSet.ValidationTrackingId,
                                   validationSet.PackageId,
                                   validationSet.PackageNormalizedVersion,
                                   validationSetDuration,
                                   _validationConfiguration.TimeoutValidationSetAfter);
                _telemetryService.TrackValidationSetTimeout(validationSet.PackageId, validationSet.PackageNormalizedVersion, validationSet.ValidationTrackingId);
            }
        }
Esempio n. 4
0
        private async Task <bool> HandleAsync(SignatureValidationMessage message, CancellationToken cancellationToken)
        {
            using (_logger.BeginScope("Handling signature validation message for package {PackageId} {PackageVersion}, validation {ValidationId}",
                                      message.PackageId,
                                      message.PackageVersion,
                                      message.ValidationId))
            {
                // Find the signature validation entity that matches this message.
                var validation = await _validatorStateService.GetStatusAsync(message.ValidationId);

                // A signature validation should be queued with ValidatorState == Incomplete.
                if (validation == null)
                {
                    _logger.LogInformation(
                        "Could not find validation entity, requeueing (package: {PackageId} {PackageVersion}, validationId: {ValidationId})",
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State == ValidationStatus.NotStarted)
                {
                    _logger.LogWarning(
                        "Unexpected signature verification status '{ValidatorState}' when 'Incomplete' was expected, requeueing (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        validation.State,
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State != ValidationStatus.Incomplete)
                {
                    _logger.LogWarning(
                        "Terminal signature verification status '{ValidatorState}' when 'Incomplete' was expected, dropping message (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        validation.State,
                        message.PackageId,
                        message.PackageVersion,
                        message.ValidationId);

                    // Consume the message.
                    return(true);
                }

                // Validate package
                using (var packageStream = await _packageDownloader.DownloadAsync(message.NupkgUri, cancellationToken))
                {
                    var result = await _signatureValidator.ValidateAsync(
                        validation.PackageKey,
                        packageStream,
                        message,
                        cancellationToken);

                    validation.State = result.State;

                    // Save any issues if the resulting state is terminal.
                    if (validation.State == ValidationStatus.Failed ||
                        validation.State == ValidationStatus.Succeeded)
                    {
                        validation.ValidatorIssues = validation.ValidatorIssues ?? new List <ValidatorIssue>();
                        foreach (var issue in result.Issues)
                        {
                            validation.ValidatorIssues.Add(new ValidatorIssue
                            {
                                IssueCode = issue.IssueCode,
                                Data      = issue.Serialize(),
                            });
                        }
                    }

                    // Save the .nupkg URL if the resulting state is successful.
                    if (validation.State == ValidationStatus.Succeeded &&
                        result.NupkgUri != null)
                    {
                        validation.NupkgUrl = result.NupkgUri.AbsoluteUri;
                    }
                }

                // The signature validator should do all of the work to bring this validation to its completion.
                if (validation.State != ValidationStatus.Succeeded &&
                    validation.State != ValidationStatus.Failed)
                {
                    _logger.LogError("The signature validator should have set the status 'Succeeded' or 'Failed', not " +
                                     "'{ValidatorState}' (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                                     validation.State,
                                     message.PackageId,
                                     message.PackageVersion,
                                     message.ValidationId);

                    return(false);
                }

                // Save the resulting validation status.
                var completed = await SaveStatusAsync(validation, message);

                if (completed && _featureFlagService.IsQueueBackEnabled())
                {
                    _logger.LogInformation("Sending queue-back message for validation {ValidationId}.", message.ValidationId);
                    var messageData = PackageValidationMessageData.NewCheckValidator(message.ValidationId);
                    await _validationEnqueuer.SendMessageAsync(messageData);
                }

                return(completed);
            }
        }
Esempio n. 5
0
        public async Task <bool> HandleAsync(SymbolsValidatorMessage message)
        {
            using (_logger.BeginScope("{ValidatorName}: Handling message for {PackageId} {PackageVersion} validation set {ValidationId}",
                                      ValidatorName.SymbolsValidator,
                                      message.PackageId,
                                      message.PackageNormalizedVersion,
                                      message.ValidationId))
            {
                if (message == null)
                {
                    throw new ArgumentNullException(nameof(message));
                }
                var validation = await _validatorStateService.GetStatusAsync(message.ValidationId);

                // A validation should be queued with ValidatorState == Incomplete.
                if (validation == null)
                {
                    _logger.LogInformation(
                        "{ValidatorName} : Could not find validation entity, requeueing (package: {PackageId} {PackageVersion}, validationId: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                else if (validation.State == ValidationStatus.NotStarted)
                {
                    _logger.LogWarning(
                        "{ValidatorName}:Unexpected status '{ValidatorState}' when 'Incomplete' was expected, requeueing package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        validation.State,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Message may be retried.
                    return(false);
                }
                // Final states
                else if (validation.State == ValidationStatus.Failed || validation.State == ValidationStatus.Succeeded)
                {
                    _logger.LogWarning(
                        "{ValidatorName}:Terminal symbol verification status '{ValidatorState}' when 'Incomplete' was expected, dropping message (package id: {PackageId} package version: {PackageVersion} validation id: {ValidationId})",
                        ValidatorName.SymbolsValidator,
                        validation.State,
                        message.PackageId,
                        message.PackageNormalizedVersion,
                        message.ValidationId);

                    // Consume the message.
                    return(true);
                }

                var validationResult = await _symbolValidatorService.ValidateSymbolsAsync(message, CancellationToken.None);

                if (validationResult.Status == ValidationStatus.Failed || validationResult.Status == ValidationStatus.Succeeded)
                {
                    validation.State           = validationResult.Status;
                    validation.ValidatorIssues = validation.ValidatorIssues ?? new List <ValidatorIssue>();
                    foreach (var issue in validationResult.Issues)
                    {
                        validation.ValidatorIssues.Add(new ValidatorIssue
                        {
                            IssueCode = issue.IssueCode,
                            Data      = issue.Serialize(),
                        });
                    }

                    if (validationResult.NupkgUrl != null)
                    {
                        validation.NupkgUrl = validationResult.NupkgUrl;
                    }

                    var completed = await SaveStatusAsync(validation, message, MaxDBSaveRetry);

                    if (completed && _featureFlagService.IsQueueBackEnabled())
                    {
                        _logger.LogInformation("Sending queue-back message for validation {ValidationId}.", message.ValidationId);
                        var messageData = PackageValidationMessageData.NewCheckValidator(message.ValidationId);
                        await _validationEnqueuer.SendMessageAsync(messageData);
                    }

                    return(completed);
                }

                _logger.LogWarning(
                    "{ValidatorName}:The validation did not return a complete status for package {PackageId} {PackageVersion} for validation id: {ValidationId} .",
                    ValidatorName.SymbolsValidator,
                    message.PackageId,
                    message.PackageNormalizedVersion,
                    message.ValidationId);
                return(false);
            }
        }