NuGet.Services.Validation.Orchestrator
Overview
The Validation Orchestrator is a .NET Framework 4.7.2 console executable that manages (“orchestrates”) the end-to-end validation pipeline for packages submitted to nuget.org. It does not perform validation work itself — instead it acts as a state machine and dispatcher, coordinating a configurable graph of downstream validator jobs. When a package or symbol package is first published (or manually revalidated), itsPackageStatusKey is set to Validating. The orchestrator’s job is to ensure that status eventually transitions to either Available or FailedValidation by driving all configured validators to completion.
The orchestrator runs as two separate deployment instances that share most of their code but have distinct Service Bus topics, validator sets, and configuration: one for
.nupkg packages and one for .snupkg symbol packages.Role in the NuGetGallery Ecosystem
Upstream: NuGetGallery
NuGetGallery enqueues a
ProcessValidationSet Service Bus message when a package is published or an admin requests revalidation. It also creates the initial validation set record in the Validation DB.Downstream: Validators
Each validator is a separate job (e.g., ProcessSignature, ValidateCertificate, ScanAndSign, SymbolsValidator) that the orchestrator starts and polls via its own Service Bus topic.
Downstream: Db2Catalog
When a package is marked
Available, its LastEdited timestamp is updated, which triggers the Db2Catalog job to pick up the package and publish it into the V3 NuGet protocol feed.Downstream: Email Job
On terminal outcomes (success or failure), the orchestrator enqueues email notifications to package owners via a dedicated email Service Bus topic.
Orchestration Algorithm
The core loop executed for each incoming Service Bus message:- Look up (or create) a
PackageValidationSetfor the given tracking ID. - For each in-progress (
Incomplete) validation, callGetResponseAsyncon its validator.- If succeeded or failed, persist the new status and call
CleanUpAsync.
- If succeeded or failed, persist the new status and call
- For each not-started validation whose prerequisites are met, call
StartAsync.- Repeat this loop if any start attempt returns
Succeededimmediately (handles synchronous validators; capped at 20 iterations).
- Repeat this loop if any start attempt returns
- Evaluate the outcome:
- Any required validation failed — mark package
FailedValidation, send failure email. - All required validations succeeded — mark package
Available, send publish email. - Still in progress — re-enqueue a
ProcessValidationSetmessage with a delay (ValidationMessageRecheckPeriod).
- Any required validation failed — mark package
- Validators can also send a
CheckValidator“queue-back” message when they finish, so the orchestrator reacts immediately rather than waiting for the scheduled recheck.
Service Bus Message Shapes
Key Files and Classes
Dependencies
Internal Project References
Key NuGet / Framework Dependencies
Notable Patterns and Implementation Details
Dual-mode deployment. A single compiled binary serves as both the Package Orchestrator and the Symbols Orchestrator. The
OrchestrationRunnerConfiguration.ValidatingType config value (Package or SymbolPackage) switches which message handler, validators, file metadata service, and status processor are registered — resolved entirely at DI composition time in Job.ConfigureAutofacServices and Job.ConfigureJobServices.Validator dependency graph. Each
ValidationConfigurationItem carries a RequiredValidations list (validator names that must reach Succeeded before this validator starts). ValidationSetProcessor.ArePrerequisitesMet checks that all named prerequisites are satisfied. TopologicalSort verifies there are no cycles at startup via ConfigurationValidator.Validate().AllowedToFail validators. A validator with FailureBehavior = AllowedToFail is optional — its failure does not block the package from becoming Available. However, if such a validator is still Incomplete when all required validators succeed, the orchestrator marks the package Available immediately and continues scheduling rechecks until the optional validator reaches a terminal state, then deletes the validation-storage blob.Process recycling pattern.
OrchestrationRunner starts the subscription processor, sleeps for ProcessRecycleInterval (typically ~24 hours), then initiates a graceful shutdown and the executable exits. The host restarts it (managed by NSSM, per Scripts/nssm.exe). This bounds memory growth and ensures periodic config and certificate refresh without requiring a true long-running daemon.