SnapshotAzureBlob
Overview
SnapshotAzureBlob is a small console-based background job that iterates every blob in a specified Azure Blob Storage container and creates a point-in-time snapshot for each blob that does not yet have one. It is designed to run on a schedule (continuously or once) and provides a simple, low-configuration safety net against accidental blob deletion or corruption.
The job targets .NET Framework 4.7.2 and integrates with the shared NuGet.Jobs.Common infrastructure used across all NuGet gallery background jobs.
A snapshot is only created when a blob has exactly one entry in its blob listing (i.e., the base blob itself with no existing snapshot). This makes the job idempotent for blobs that already have at least one snapshot — it will never pile up duplicate snapshots in a single run.
Role in System
Within the NuGetGallery ecosystem, blob storage containers hold essential artifacts such as package files, statistics exports, and auxiliary search data.SnapshotAzureBlob acts as a data-durability guardrail: by maintaining at least one snapshot per blob, operations teams can restore a prior version of any blob without needing a full storage account backup.
Data Protection
Prevents permanent data loss from accidental writes or deletions by preserving a recoverable snapshot of every blob.
Scheduled Job
Runs via the shared
JobRunner loop — can execute once or continuously with a configurable sleep interval.Parallel Execution
Uses
Parallel.ForEach to snapshot blobs concurrently, minimising total wall-clock time for large containers.Application Insights
Emits structured telemetry through
Microsoft.Extensions.Logging with reserved event IDs in the 800 range.Key Files / Classes
| File | Class / Type | Purpose |
|---|---|---|
Program.cs | Program | Entry point. Instantiates SnapshotAzureBlobJob and hands off to JobRunner.Run(). |
SnapshotAzureBlobJob.cs | SnapshotAzureBlobJob | Core job logic. Implements JobBase.Init() and JobBase.Run(). Parses args, connects to Azure Storage, and drives the snapshot loop. |
ArgumentNames.cs | ArgumentNames | Static constants for the two required CLI arguments: ConnectionString and Container. |
LogEvents.cs | LogEvents | Defines structured EventId constants in the reserved 800–802 range for this job. |
Dependencies
NuGet Packages
| Package | Purpose |
|---|---|
WindowsAzure.Storage | Legacy Azure Blob Storage SDK. Provides CloudStorageAccount, CloudBlobClient, CloudBlockBlob, and the synchronous Snapshot() API. |
System.ComponentModel.EventBasedAsync | Provides IServiceContainer used by JobBase.Init() for service resolution. |
Internal Project References
| Project | Purpose |
|---|---|
NuGet.Jobs.Common | Shared job infrastructure: JobBase, JobRunner, JobConfigurationManager, Application Insights wiring, and logging setup. |
Runtime Arguments
The job accepts the following command-line arguments passed as-ArgName value pairs:
| Argument | Required | Description |
|---|---|---|
-ConnectionString | Yes | Azure Storage connection string for the account containing the target container. |
-Container | Yes | Name of the blob container whose blobs should be snapshotted. |
-InstrumentationKey | Recommended | Application Insights instrumentation key for telemetry. |
-Once | No | Run a single iteration instead of looping continuously. |
-Sleep | No | Milliseconds to sleep between continuous iterations (default: 5000). |
-Interval | No | Seconds between iterations (alternative to -Sleep). |
Notable Patterns and Implementation Details
Snapshot guard logic —
EnsureOneSnapshot performs a flat container listing with BlobListingDetails.None, then re-queries each blob by name prefix with BlobListingDetails.Snapshots. Only when expandedList.Count() == 1 (base blob present, no snapshots yet) does it call blob.Snapshot(). A container that was already snapshotted will produce zero new snapshots on the next run.Log Events
| Event ID | Name | Severity | When Emitted |
|---|---|---|---|
| 800 | JobRunFailed | — | Reserved; surfaced by JobRunner on unhandled run failure. |
| 801 | JobInitFailed | — | Reserved; surfaced by JobRunner on initialisation failure. |
| 802 | SnaphotFailed | Critical | Emitted per-blob when blob.Snapshot() throws an exception. |
Event ID 802 is named
SnaphotFailed (single ‘s’ — “Snashot”) in the source. This is a typo that has been preserved as-is to avoid breaking any existing Application Insights queries or alerts that filter on the event name string.