Skip to content

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 tenantId before touching a store; no cross-tenant work.
  • Trace propagationtraceId/correlationId flow 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.