Handlers: Translating Queue Messages to WebSockets
The Handlers module contains the Wolverine message consumers responsible for receiving asynchronous events from the RabbitMQ "notifications" queue and seamlessly broadcasting them over SignalR.
Business Logic Intent
The handlers act as the critical bridge between backend domain logic (or background processing) and the client interface. Because Wolverine creates a fresh instance of the handler class for every incoming message, NotificationHandler operates strictly statelessly. Its sole intent is mapping inbound message payloads—produced by the API or DocumentGenerator workers—into tightly controlled outward-facing SignalR event DTOs, and then distributing those payloads precisely to the relevant Hub groups.
This separation ensures that producers (like the API) only need to fire a single “fire-and-forget” Wolverine message. They have zero knowledge of WebSockets, scaling constraints, or currently connected clients. The Handler takes on the responsibility of real-time fan-out.
Message Handling Lifecycle
- Wolverine Invocation: Wolverine reads a message from RabbitMQ. Using the
[MessageIdentity]string in the payload, it matches the message to the correspondingHandle(NotifyXMessage message)method inNotificationHandler.cs. - Dependency Injection: Wolverine instantiates the handler, automatically injecting
IHubContext<DocumentHub>andILogger. - Payload Translation: The handler constructs a tailored SignalR event DTO (e.g., transforming a
NotifyProgressMessageinto aDocumentProgressEvent). - Targeted Broadcast: Instead of a global broadcast, the handler uses
IHubContextto send the event to two distinct SignalR groups:- Document Group (
doc-{DocumentId}): Ensures users staring at the detailed document editor see instant updates (like blocks completing or structural sections being added). - Project Group (
project-{ProjectId}): Ensures users looking at a high-level project dashboard see aggregate progress updates without needing full block-level detail.
- Document Group (
Handled Message Mappings
The table below outlines how backend queue events are translated into frontend real-time actions.
| Inbound Wolverine Message | SignalR Event Name / Type | Purpose |
|---|---|---|
NotifyProgressMessage | "Progress" / DocumentProgressEvent | Updates the generation progress bar. |
NotifyCompletedMessage | "DocumentCompleted" / DocumentCompletedEvent | Signals total completion of the AI saga. |
NotifyErrorMessage | "Error" / DocumentErrorEvent | Propagates a fatal or localized generation error to the UI. |
NotifyDocumentUpdatedMessage | "DocumentUpdated" / DocumentUpdatedEvent | Signals high-level status changes (e.g., from “Drafting” to “Review”). |
NotifyBlockUpdatedMessage | "BlockUpdated" / BlockUpdatedEvent | Pushes the actual generated AI content (or status) for a single block to the editor. |
NotifyBlocksAddedMessage | "BlocksAdded" / BlocksAddedEvent | Notifies the editor that new dynamic child blocks were spawned by the generator. |
NotifySectionsAddedMessage | "SectionsAdded" / SectionsAddedEvent | Notifies the editor of a new section outline. |
NotifyBlockRemovedMessage | "BlockRemoved" / BlockRemovedEvent | Synchronizes deletion of a block. |