This guide provides a comprehensive overview and step-by-step tutorial for extending the Backpack system by implementing a new Processor.
Processors are the ecosystem-specific logic units of Backpack. They are responsible for:
- Metadata Extraction: Communicating with upstream registries (NPM, NuGet, Maven, etc.) to fetch artifact data.
- Dependency Resolution: Parsing manifests (e.g.,
package.json,.nuspec) to build a dependency graph. - File Identification: Mapping remote version strings to specific physical file URIs for collection.
Backpack utilizes an exhaustive recursive discovery pattern. When a Processor identifies a dependency, it adds it to the dependencies list rather than fetching it directly. The Core.Gateway detects these new dependencies and automatically triggers new processing requests, continuing the cycle until the entire dependency tree is mirrored locally.
Backpack provides a standardized .NET template to accelerate development.
Run the following command from the root of the repository:
dotnet new install ./Templates/ProcessorTemplateCreate a directory for your new processor and run the template (using Go Modules as an example):
mkdir Processor.Go
cd Processor.Go
# -n: The name of the processor (PascalCase)
# --ENDPOINT: The message queue endpoint name (lowercase)
# --BASE_URL: The upstream registry URL
dotnet new backpack-processor -n Go --ENDPOINT go --BASE_URL https://proxy.golang.orgAfter scaffolding, add the new .csproj to the Backpack.sln solution.
The template generates a business logic class (e.g., Go.cs) implementing an interface (e.g., IGo.cs). Your goal is to populate the Artifact object with versions, files, and dependencies.
public async Task<Artifact> ProcessArtifact(Artifact artifact) {
logger.LogInformation("Processing Go module {Id}...", artifact.id);
// 1. Fetch metadata from the upstream registry (e.g., https://proxy.golang.org/<module>/@v/list)
var versions = await FetchVersionsFromUpstream(artifact.id);
foreach (var v in versions) {
// 2. Add the version to the artifact
var artifactVersion = new ArtifactVersion { version = v };
// 3. Add the physical files that need to be collected
// The Gateway will route these to the appropriate Collector (HTTP, Git, etc.)
artifactVersion.AddFile(
name: $"{artifact.id}-{v}.zip",
uri: $"{_baseUrl}/{artifact.id}/@v/{v}.zip"
);
artifact.AddVersion(artifactVersion);
// 4. Resolve and add dependencies for this version
// This triggers the recursive Exhaustive collection logic
var deps = await ResolveDependencies(artifact.id, v);
foreach (var dep in deps) {
artifact.AddDependency(dep.Id, "go");
}
}
return artifact;
}To understand how your code triggers system-wide behavior, follow this lifecycle:
- Request: The
Core.Gatewaysends anArtifactProcessRequestto your processor's endpoint (go). - Resolution: Your
Go.cslogic fetches metadata and identifies all versions, files, and dependencies. - Reply: The
Consumer.cscallscontext.ProcessorReply(artifact), sending the populated object back to the Gateway. - Collection: The Gateway inspects the
filesin eachArtifactVersionand sendsArtifactCollectRequestmessages to the specialized Collectors (e.g.,Collector.Http). - Recursion: The Gateway inspects the
dependenciesand triggers newArtifactProcessRequestmessages for those artifacts, continuing until the entire tree is mirrored locally.
- Deployment: Deploy your new microservice container to your infrastructure.
- Web GUI: Register the new processor endpoint (
go) in the Backpack Dashboard. - Trigger: Use the "Add Artifact" form in the GUI to request a package from the new ecosystem and monitor the "Status" page for message flow.
While the .NET template is recommended for native integration, processors can be implemented in any language that supports RabbitMQ and JSON serialization.
- Message Schema: Refer to the Raw Integration Guide for technical details on
ArtifactProcessRequestandArtifactProcessedRequest. - MassTransit Compatibility: Ensure your JSON message structures and headers are compatible with MassTransit's serialization format.
- Atomic Operations: Use the
Artifactmodel's helper methods (AddVersion,AddFile,AddDependency) to maintain consistent state. - Observability: Leverage the provided
ILogger. Logs and traces are automatically captured by OpenTelemetry. - Resilience: Processors are designed to be stateless. If metadata fetching fails, throwing an exception will trigger the system-wide retry policy.