Notifications Infrastructure

Architectural Context

The Notifications Subsystem inside MILTON.DocumentGenerator bridges the gap between the headless Document Processing Saga and the user interface. It is responsible for publishing document-level progress, completion, and error states.

Business Logic Intent

Because the MILTON.DocumentGenerator worker is a disconnected backend service processing intensive AI generation tasks over long periods, it cannot communicate with the React frontend directly via WebSockets. Instead, it relies on Wolverine messaging and RabbitMQ. The primary intent of this infrastructure is to emit purely Document-level status updates. Fine-grained block or section-level notifications are intentionally left out; those are emitted by the API when it applies the generated block results to the database.

Architecture & Integration

The Document Generator implements an inverted dependency model for notifications:

  • IUserNotifier Interface: Exposes simple asynchronous methods: NotifyProgressAsync, NotifyCompletedAsync, and NotifyErrorAsync. This decouples the core Saga logic from the messaging transport.
  • WolverineUserNotifier: The concrete implementation that translates interface calls into Wolverine IMessageBus.PublishAsync calls.
  • Message Identity Parity: The published messages (NotifyProgressMessage, NotifyCompletedMessage, NotifyErrorMessage) are annotated with Wolverine [MessageIdentity] attributes (e.g., notify-progress). The MILTON.NotificationService has structurally identical records and consumes these messages to broadcast them over SignalR.

Mermaid Sequence Diagram

The following sequence illustrates how the Document Generator notifies the end user of its progress.

sequenceDiagram
    autonumber
    participant Saga as DocumentProcessingSaga
    participant Notifier as WolverineUserNotifier
    participant Bus as Wolverine IMessageBus
    participant Rabbit as RabbitMQ
    participant SignalR as MILTON.NotificationService

    Saga->>Notifier: NotifyProgressAsync(docId, "Processing...")
    Notifier->>Bus: PublishAsync(NotifyProgressMessage)
    Bus->>Rabbit: Route via MessageIdentity("notify-progress")
    Note over Rabbit, SignalR: Asynchronous message queue
    Rabbit->>SignalR: Consume(NotifyProgressMessage)
    SignalR->>SignalR: Map to SignalR event
    SignalR-->>UI: WebSocket Push

0 items under this folder.