Overview
NuGet.Jobs.Auxiliary2AzureSearch is a scheduled background job that keeps the NuGet.org Azure Search “search” index and its associated auxiliary files in sync with the current state of the Gallery database and the statistics pipeline. It runs continuously as a singleton Windows service and performs three incremental update passes on every execution:
- Verified packages — updates
verified-packages/verified-packages.v1.jsonin Blob Storage when the set of prefix-reserved package IDs changes. - Downloads — fetches the latest
downloads.v1.jsonfrom the statistics pipeline URL, diffs it against the previously indexed copy, applies popularity-transfer adjustments, and pushes changed download counts to the Azure Search “search” index in parallel batches. - Owners — fetches the current owner map from Gallery DB, diffs it against the previously indexed copy, pushes changed owner arrays to the “search” index, and appends a timestamped change-history file to Blob Storage for audit purposes.
This job is a singleton. Only one instance must run per Azure Search resource at any given time. Running multiple instances against the same resource will cause conflicting writes and data corruption.
Role in the System
Search Subsystem
Feeds real-time download counts, owner lists, and verified-package flags into the Azure Search “search” index so that
NuGet.Services.SearchService can surface accurate metadata without querying the Gallery database on every request.Auxiliary File Store
Maintains the canonical copies of the four search auxiliary files in Azure Blob Storage (
downloads.v2.json, owners.v2.json, verified-packages.v1.json, popularity-transfers.v1.json).Statistics Bridge
Bridges the statistics pipeline (which produces
downloads.v1.json at a public URL) into the Azure Search index, applying popularity-transfer scoring adjustments as configured.Prerequisite: Db2AzureSearch
Requires
NuGet.Jobs.Db2AzureSearch to have performed the initial full index population. Auxiliary2AzureSearch only handles incremental updates from that baseline forward.Key Files and Classes
| File Path | Class | Purpose |
|---|---|---|
Program.cs | Program | Entry point; delegates to JobRunner.Run |
Job.cs | Job | Registers DI services; binds Auxiliary2AzureSearchConfiguration and the DownloadsV1JsonClient |
Auxiliary2AzureSearchCommand.cs | Auxiliary2AzureSearchCommand | Orchestrator; runs the three sub-commands in sequence and emits an end-to-end telemetry event |
UpdateVerifiedPackagesCommand.cs | UpdateVerifiedPackagesCommand | Diffs old vs new verified-package sets via symmetric-except; replaces the blob only when changed |
UpdateDownloadsCommand.cs | UpdateDownloadsCommand | Core download-sync logic: fetches, cleans, diffs, applies popularity transfers, batches and pushes to Azure Search |
UpdateOwnersCommand.cs | UpdateOwnersCommand | Diffs owner sets, pushes changed owner arrays to Azure Search, persists a change-history blob, replaces owners.v2.json |
DataSetComparer.cs | DataSetComparer | Generic two-pass set comparer used for owner and popularity-transfer diffs |
DownloadSetComparer.cs | DownloadSetComparer | Compares old vs new download counts; enforces MaxDownloadCountDecreases guard to prevent corrupt statistics from wiping download history |
Auxiliary2AzureSearchConfiguration.cs | Auxiliary2AzureSearchConfiguration | Configuration POCO — extends AzureSearchJobConfiguration with DownloadsV1JsonUrl, MinPushPeriod, and MaxDownloadCountDecreases |
Scripts/Functions.ps1 | — | PowerShell helpers for installing/uninstalling the job as a Windows service via NSSM |
Dependencies
Internal Project References
| Project | Purpose |
|---|---|
NuGet.Jobs.Common | JobRunner, AzureSearchJob<T>, IAzureSearchCommand base infrastructure |
NuGet.Services.AzureSearch | All Auxiliary2AzureSearch command implementations, auxiliary-file clients, IBatchPusher, telemetry service |
Key NuGet Package Dependencies
| Package | Purpose |
|---|---|
NuGet.Packaging | PackageIdValidator used to clean invalid IDs from download data |
NuGet.Versioning | NuGetVersion parsing and normalization during download-data cleaning |
Microsoft.Extensions.Options | IOptionsSnapshot<Auxiliary2AzureSearchConfiguration> for runtime config |
The project targets net472 and produces a console executable. It is deployed as a Windows service using NSSM (Non-Sucking Service Manager), bundled as
Scripts/nssm.exe.Configuration Reference
Notable Patterns and Implementation Details
Popularity transfers are double-gated.
UpdateDownloadsCommand checks both the EnablePopularityTransfers configuration property and the IFeatureFlagService runtime flag. If either is disabled, all transfers are treated as empty, effectively removing any previously applied transfer boosts on the next run.DataSetComparer.CompareOwners uses ordinal string comparison for owner usernames (not ordinal-ignore-case) so that a username case change is correctly detected as a change and propagated to the index. Popularity-transfer comparisons use ordinal-ignore-case because casing changes in package IDs are considered insignificant there.Owner change-history files are written to
owners/changes/TIMESTAMP.json with a path timestamp formatted as yyyy-MM-dd-HH-mm-ss-FFFFFFF (UTC). These files are append-only and exist solely for future forensic and auditing purposes. They intentionally omit owner usernames to comply with GDPR requirements.