Workers¶
Target Architecture — Final-State Design
The 7 workers below are the planned asynchronous processors of the ConnectSoft.Factory.Templates.* services. They are hosted as WorkerTemplate-style consumers on Azure Service Bus via ConnectSoft.Extensions.MessagingModel.MassTransit and react to commands (VerbNoun) and events (NounVerbPastTense) in the canonical event envelope.
Workers do the heavy, long-running, and event-reactive work of the platform: validating templates, generating scaffolds, recomputing compatibility, planning upgrades, indexing libraries, scanning dependency graphs, and publishing packages. Each is idempotent (deduplicating on eventId + handler name) and tenant-scoped.
Worker inventory¶
| Worker | Trigger | Purpose | Input | Output | Retry | Idempotency |
|---|---|---|---|---|---|---|
TemplateValidationWorker |
ValidateTemplate command / TemplateVersionCreated |
Lint and structurally verify a template version | templateVersionId, check set |
TemplateValidationResult, TemplateValidated |
Exponential backoff, 5 attempts → DLQ | Dedup on templateVersionId + check-set hash; result upsert |
TemplateScaffoldWorker |
GenerateScaffold command |
Execute a template asynchronously and produce output | executionId, version, parameters, libraries, target |
ScaffoldOutput, ScaffoldGenerated, TemplateExecuted |
Backoff, 3 attempts → DLQ | Dedup on executionId; content-hash guards duplicate output |
TemplateCompatibilityWorker |
LibraryVersionCreated / TemplateVersionCreated / TemplatePublished |
Recompute affected compatibility matrices | changed subject ref | updated CompatibilityMatrix, CompatibilityEvaluated |
Backoff, 5 attempts → DLQ | Dedup on subject ref + version; matrix recompute is deterministic |
TemplateUpgradeWorker |
TemplatePublished (new major/minor) |
Compute upgrade plans for dependent products | new templateVersionId |
TemplateUpgradePlan, TemplateUpgradePlanCreated |
Backoff, 5 attempts → DLQ | Dedup on (templateId, fromVersion, toVersion); plan upsert |
LibraryIndexingWorker |
LibraryRegistered / LibraryVersionCreated |
Index package + capabilities for search and Knowledge | libraryId/libraryVersionId |
search index entry, LibraryIndexed |
Backoff, 5 attempts → DLQ | Dedup on libraryVersionId; index write is idempotent upsert |
DependencyScanWorker |
LibraryVersionCreated |
Resolve & persist the dependency graph for a version | libraryVersionId, declared deps |
updated DependencyGraph, DependencyScanned |
Backoff, 5 attempts → DLQ | Dedup on libraryVersionId; graph node upsert by version |
PackagePublishWorker |
PublishPackage command / approved PackagePublication |
Push package to Azure Artifacts (NuGet) | libraryVersionId, feed target |
published NuGet package, LibraryPublished |
Backoff, 3 attempts → DLQ; publish is verified | Dedup on libraryVersionId + feed; NuGet push is naturally idempotent per version |
Event-flow diagram¶
flowchart TB
TVcreated["TemplateVersionCreated"] --> TVW["TemplateValidationWorker"]
TVW --> TValidated["TemplateValidated"]
TValidated --> TPub["TemplatePublished"]
TPub --> TCW["TemplateCompatibilityWorker"]
TPub --> TUW["TemplateUpgradeWorker"]
TCW --> CEval["CompatibilityEvaluated"]
TUW --> TUPlan["TemplateUpgradePlanCreated"]
GenCmd["GenerateScaffold (command)"] --> TSW["TemplateScaffoldWorker"]
TSW --> SGen["ScaffoldGenerated"]
SGen --> TExec["TemplateExecuted"]
TExec --> DevOps["DevOps & GitOps"]
LVcreated["LibraryVersionCreated"] --> DSW["DependencyScanWorker"]
LVcreated --> LIW["LibraryIndexingWorker"]
DSW --> DScanned["DependencyScanned"]
LIW --> LIndexed["LibraryIndexed"]
DScanned --> TCW
PubCmd["PublishPackage (command)"] --> PPW["PackagePublishWorker"]
PPW --> LPub["LibraryPublished"]
LPub --> Marketplace["Marketplace"]
LIndexed -.-> Knowledge["Knowledge Platform"]
SGen -.-> Observability["Observability & Feedback"]
Hold "Alt" / "Option" to enable pan & zoom
Cross-cutting worker behavior¶
- Idempotency — every consumer derives an idempotency key from
eventId+ handler name (per the event envelope consumer rules) and records processed keys; replays are safe. - Retry & poison handling — transient failures retry with exponential backoff; exhausted messages move to a dead-letter subqueue with the full envelope preserved for replay.
- Tenant guard — each handler asserts
tenantIdbefore touching a store; no cross-tenant work. - Trace propagation —
traceId/correlationIdflow into OpenTelemetry spans and Serilog context so generation, validation, and publishing are correlated end to end in Observability & Feedback. - Ordering — workers tolerate out-of-order delivery; compatibility recompute and upgrade planning are derived from current persisted state, not message order.