Jeff
Jeff

Reputation: 36573

CQRS NServiceBus UI Feedback

I have a CQRS solution leveraging NServiceBus with web workers in an HTML/JavaScript app.

I have the scenario

I want to provide feedback to the user in the UI once everything completes (but not block the UI).

I know that I can use Bus.Return to return from my Bus.Send to the CommandHandler when I use, indicating its work has completed. But how can I give feedback once the EventHandlers triggered by Bus.Publish have finished their work?

I can use Bus.Reply from the EventHandler...but how to get back to the original sender? Do I really need to use a Saga to accomplish this? And if I do and ReplyToOriginator, once the reply has been received by the originator, how do I correlate the reply to the correct user/UI to notify? Do I have to keep track of all requests pending notification somewhere? It seems overly complex.

Upvotes: 3

Views: 707

Answers (3)

radu-matei
radu-matei

Reputation: 3520

I don't think that updating the user's UI without confirmation of the command's success is the best approach.

For this purpose I use a real-time framework called SignalR in which you can have real-time calls between the server and the client.

http://www.asp.net/signalr

The CommandHandler executes the command, then the event is fired and I use most of the events mainly to update the read data and the UI.

In the event handler you can call server methods from the SignalR hubs(and to answer specifically your question, you can get back to your original sender by getting his SignalR ConnectionId) (googling "signalr get client connection id") might help you get back to the original sender)

Upvotes: 0

Alexey Zimarev
Alexey Zimarev

Reputation: 19640

This question has been asked on SO many times.

If you look at Udi's Longest Post, you will read that the general assumption that a command handler should be expected never to fail. As Greg Young suggests, the chance of it to fails is marginal so in this case automation is not required to handle this small number of cases, when it could easily be handler by human intervention. Concerning the UI updates, Udi suggests (in the same post) that the UI is updated with the data that has been sent inside the command. Meaning, the UI is showing the data under an assumption that the command was properly handled and read model updated. Surely, nothing stops you from using Bus.Return or Bus.Reply and sometimes you must use it because you expect not only a status but some actual data to be returned, but this is a different thing. In many cases, UI of highly loaded systems work like this. The UI shows the data as it has been updated on the server. Later in time, the UI can receive a failure event saying there was an error and the data is updated from the read model, the command needs to be repeated. I believe that the most pragmatic approach is to expect success, not failure, this is how the system normally works, and after this is done, create some mechanist to publish error notifications. If no error is received, the assumption should be that everything went well.

In his "Implementing DDD" book, Vaughn Vernon mentions this approach but states that despite many see it as an efficient pattern, other criticise it as a "hack". So, I would assume there is no "right way" invented so far and everyone decides according to the requirements and user acceptance rate.

From what Greg Young says about service bus being used for events distribution, I conclude that ES with catch up subscription is an easier and more reliable way for read model updates than using a pub-sub.

Upvotes: 1

Phil Sandler
Phil Sandler

Reputation: 28036

It sounds like the WebAPI service is interested in knowing when XXX work is completed by the "Domain" endpoint. If that's the case, it would make sense to simply publish an event from the Domain endpoint, and then anyone who cares about that type of work being completed can subscribe to that event type. An event is essentially an interesting change in state, so if the work being completed represents an interesting change in state, publishing event makes perfect sense.

As you noted, a Bus.Reply() would also work. I tend to prefer using an event to avoid the explicit request/response paradigm.

One the event/response is received, providing that information back to the user/browser is the WebAPI service's problem, so would require some form of state tracking. A saga, database or in-memory construct could work, but also could be possible by passing a correlation Id with the message in both directions, depending on how you are getting the information back to the user (e.g. SignalR).

Upvotes: 1

Related Questions