Real-time Flows
SignalR Hub Group Map
flowchart LR
subgraph BouquetHub
RG["radius:{lat}:{lng}:{radius}\n(Customer: nearby bouquet updates)"]
OG["order:{orderId}\n(Customer: order status updates)"]
VG["vendor:{vendorId}\n(Vendor Portal: order + vase dashboard)"]
end
Customer -->|JoinRadiusGroup| RG
Customer -->|JoinOrderGroup| OG
VendorPortal -->|JoinVendorGroup| VG
Outbox → EventBus → SignalR Dispatch
sequenceDiagram
participant Handler as Command Handler
participant UoW as UnitOfWork (EF Core)
participant DB as PostgreSQL (outbox_messages)
participant Dispatcher as OutboxDispatcherService (BackgroundService)
participant Bus as InMemoryEventBus
participant Hub as BouquetHub (SignalR)
participant Client as Connected Client
Handler->>UoW: SaveChangesAsync()
UoW->>DB: INSERT aggregate change + INSERT outbox_messages in same transaction
loop Every 5s
Dispatcher->>DB: SELECT top 20 WHERE processed_at IS NULL ORDER BY created_at
DB-->>Dispatcher: [OutboxMessage]
Dispatcher->>Dispatcher: Deserialize IDomainEvent from payload
Dispatcher->>Bus: InMemoryEventBus.PublishAsync(event)
Bus->>Hub: Matching event handler calls Hub.Clients.Group(...).SendAsync("OrderStatusChanged", ...)
Hub-->>Client: Real-time message (WebSocket)
Dispatcher->>DB: UPDATE outbox_messages SET processed_at = now
end
⚠️ Known gap (EP-09):
RabbitMQEventBus.PublishAsyncreturnsTask.CompletedTask— all events published through it are silently dropped.InMemoryEventBusis the real implementation. Production nuance: prod appsettings setsEventBus:Type=RabbitMQ, which selects the stub — soIEventBus-published events are dropped in prod. The outbox pattern (OutboxDispatcherService, shown above) is the actual event-delivery path in production and is unaffected. Fix: wire real RabbitMQ publish in EP-09 S-09-06.
⚠️ Known gap (EP-06):
DeviceRegistrationaggregate and repository are implemented. FCM push notification dispatch (INotificationServiceClient) is a stub — push notifications are not delivered to mobile devices. Fix planned in EP-06.
Bouquet View Counter
sequenceDiagram
participant App as Mobile App
participant API as REST API
participant Counter as BouquetViewCounterService
participant Hub as BouquetHub (SignalR)
participant Vendor as Vendor Portal (subscribed to vendor group)
App->>Hub: SignalR: StartViewingBouquet(bouquetId)
Hub->>Counter: BouquetViewCounterService.IncrementViewCount(bouquetId, connectionId)
Counter->>Hub: SendAsync("BouquetViewCountChanged", bouquetId, count)
Hub-->>Vendor: Real-time view count update on dashboard