Notification Service (MILTON.NotificationService)

Overview

The Notification Service is a standalone ASP.NET Core microservice that bridges RabbitMQ messaging and SignalR real-time push for the MILTON platform. It consumes notification messages published by backend workers (DocumentGenerator, API) and broadcasts them to connected Blazor clients via a SignalR hub.

This service exists as a separate process so that:

  • The API server is not burdened with long-lived WebSocket connections.
  • SignalR can scale independently from the API and worker services.
  • The YARP gateway terminates TLS and routes /hubs/* traffic to this service.

Architecture

flowchart LR
    subgraph Producers
        DG["DocumentGenerator"]
        API["MILTON API"]
    end

    RMQ["RabbitMQ<br/>notifications queue"]

    subgraph NotificationService["MILTON.NotificationService"]
        WH["Wolverine Handlers<br/>(NotificationHandler)"]
        Hub["DocumentHub<br/>/hubs/document"]
    end

    subgraph Clients["Blazor WASM Clients"]
        DE["DocumentEditor"]
        DL["DocumentsList"]
        PD["ProjectDashboard"]
    end

    Producers -- "publish messages" --> RMQ
    RMQ -- "consume" --> WH
    WH -- "broadcast via<br/>IHubContext" --> Hub
    Hub -- "SignalR<br/>WebSocket" --> Clients

Technology

ConcernTechnology
RuntimeASP.NET Core 10
MessagingWolverine + RabbitMQ
Real-time pushSignalR
Orchestration.NET Aspire

Key Files

FilePurpose
Program.csService bootstrap — configures SignalR, Wolverine RabbitMQ listener on "notifications" queue
DocumentHub.csSignalR hub with document-level and project-level group management
NotificationHandlers.csWolverine message handlers that map each message type to a SignalR broadcast

DocumentHub

The hub exposes four client-callable methods for group membership:

MethodGroup NameUsed By
JoinDocumentGroup(Guid)doc-{documentId}DocumentEditor
LeaveDocumentGroup(Guid)doc-{documentId}DocumentEditor
JoinProjectGroup(int)project-{projectId}ProjectDashboard, DocumentsList
LeaveProjectGroup(int)project-{projectId}ProjectDashboard, DocumentsList

All server-to-client events are sent to both the document group and the project group, so list pages and detail editors both receive updates.

Handled Messages

Each Wolverine message is consumed from the "notifications" RabbitMQ queue and broadcast as a SignalR event:

Wolverine MessageSignalR EventPayload
NotifyProgressMessage"Progress"DocumentProgressEvent
NotifyCompletedMessage"DocumentCompleted"DocumentCompletedEvent
NotifyErrorMessage"Error"DocumentErrorEvent
NotifyDocumentUpdatedMessage"DocumentUpdated"DocumentUpdatedEvent
NotifyBlockUpdatedMessage"BlockUpdated"BlockUpdatedEvent
NotifyBlocksAddedMessage"BlocksAdded"BlocksAddedEvent
NotifySectionsAddedMessage"SectionsAdded"SectionsAddedEvent
NotifyBlockRemovedMessage"BlockRemoved"BlockRemovedEvent

Message contracts are defined in MILTON.Shared/Messaging/Notifications/. Event records are defined in MILTON.Shared/DTOs/Notifications/.

Aspire Integration

In the AppHost, this service is wired as:

var notificationService = builder.AddProject<Projects.MILTON_NotificationService>("notificationservice")
    .WithReference(rabbit)
    .WaitFor(rabbit);

The YARP gateway routes /hubs/{**remainder} to this service for TLS termination and unified entry point.

0 items under this folder.