Generators

Info

Architectural truth for Generators in the Documents feature. This leaf module acts as the API-side bridge for the asynchronous document generation pipeline, managing data gathering and persistence via CQRS messaging.

Overview

The Documents/Generators module does not execute LLM interactions or long-running computations. Instead, it owns the API side of the generation messaging contracts (coordinated via Wolverine over RabbitMQ) and the handlers that interact with milton-db (via EF Core) and S3 (via the Claim-Check pattern).

The actual computation runs in the MILTON.DocumentGenerator worker service.

Business Logic Intent

Document generation is separated into two logical halves:

  1. API (State & Storage): Owns the SQL database. It gathers context for generation (files, project presets), packages it into a claim-check, and later receives the result to save back to the database.
  2. Worker (Pure Functions): Receives a claim-check key, executes LLM prompts or Python API calls, and writes the output back to a claim-check. It never touches milton-db.

The Generators folder holds the API half of this contract, ensuring that the worker service operates statelessly.

The Claim-Check Pattern

Message brokers (RabbitMQ) struggle with large payloads (source files, generated documents). Therefore, this feature heavily uses the Claim-Check Pattern:

  1. The API gathers large context data (e.g., source code, LLM presets).
  2. It uploads this to an IClaimCheckStore (S3) and gets a string key.
  3. It sends a lightweight message (e.g., TestCaseGenerationRequested) over RabbitMQ containing just the Guid SagaId, Guid BlockId, and the ClaimCheckKey.
  4. The worker reads the S3 object, processes it, writes the result to S3, and replies with a TestCaseGenerationCompleted containing a new ResultClaimCheckKey.

Handlers & Flow

For every block type (e.g., Requirement, Scanner, TestCase), there are two handlers in this module:

  • Prepare[Type]GenerationHandler: Triggered by a command. Gathers database context, creates the claim-check payload, and fires the [Type]GenerationRequested message.
  • Apply[Type]GenerationHandler: Triggered when the worker finishes. Reads the result claim-check, updates milton-db with the new block content, and fires a BlockProcessedEvent.

Sequence: The Generation Round-Trip

sequenceDiagram
    participant API as API (milton-db)
    participant S3 as S3 (Claim-Check)
    participant Bus as Wolverine
    participant Worker as DocGen Worker

    note over API: Prepare Phase
    API->>API: Load Block & Presets from DB
    API->>S3: PutAsync(Payload)
    S3-->>API: returns InputKey
    API->>Bus: Publish(TypeGenerationRequested, InputKey)
    
    note over Worker: Execution Phase
    Bus->>Worker: Consume(TypeGenerationRequested)
    Worker->>S3: GetAsync(InputKey)
    Worker->>Worker: Run LLM / Processor
    Worker->>S3: PutAsync(Result)
    S3-->>Worker: returns ResultKey
    Worker->>Bus: Publish(TypeGenerationCompleted, ResultKey)
    
    note over API: Apply Phase
    Bus->>API: Consume(TypeGenerationCompleted)
    API->>S3: GetAsync(ResultKey)
    API->>API: Update milton-db (EF Core)
    API->>Bus: Publish(BlockProcessedEvent)

Messaging Contracts

This module defines API-side mirrors of the message contracts. To enable cross-service routing without a shared assembly, the [MessageIdentity("...")] attributes strictly match the worker’s attributes.

  • Commands (Triggered locally): PrepareRequirementGenerationCommand, PrepareScannerGenerationCommand, PrepareTestCaseGenerationCommand
  • Outgoing Events (Sent to Worker): RequirementGenerationRequested, ScannerGenerationRequested
  • Incoming Events (Received from Worker): RequirementGenerationCompleted, ScannerGenerationCompleted
  • Orchestration Events: BlockProcessedEvent, DocumentCreatedEvent, GeneratePdfCommand

0 items under this folder.