Interface update after sending a command

I am struggling to solve this architectural problem. Our system uses the NService bus and the DDD implementation with EventSourcing using NEventStore and NES. The client application is WPF

I still can’t decide what is the best way to update the user interface, for example: I have a user interface to create (Batch {Id, StartDate, EndDate, etc.)) After the user clicks on save, I send a command (CreateBatch),

Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc }); 

Now

Option number 1


Do I have to register for an answer as follows:

 private void btnSave_Click(object sender,EventsArg e){ Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc }) .Register<int>(c=> { MessageBox.Show("Command Succeded"); Close();}); } 

and server side:

 public void Hanlde(CreateBatch cmd){ //initiate aggregate and save it. Bus.Return( /*What ?? Success Code?*/); } 

In this case, how to handle errors? (Validation errors, for example, have batch starts already started on the same date?), Since you can only return int or string !!

Option number 2:


Send a command, close the window, fake the record added to the main grid until the user updates the grid and receives real information from the ReadModel database or finds out that the record has not yet been added, not having a clue about what happened !!

 private void btnSave_Click(object sender,EventsArg e){ Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc }); Close(); } 

Option number 3


Send a command, close the window, fake that the record has been added to the main grid, but mark it as (in progress), wait for the (BatchCreated) event to make sure that this is the same batch identifier that we sent earlier, and then mark the entry as saved in the grid.

 private void btnSave_Click(object sender,EventsArg e){ Bus.Send<CreateBatch> (batch => {batch.Id = Guid.NewGuid(); .... etc }); Close(); } public class BatchHandler : IHandleMessages<BatchCreated> { public void Handle(BatchCreated evnt) { if(SomeCachForSentIDS.Contains(evnt.BatchId) ///Code to refresh the row in the grid and reflect that the command succeeded. } } 

If you have any better options or if you have suggestions for these parameters or even some links on how to handle this situation, I would be grateful.

Thanks.

+6
source share
2 answers

One of the important principles when implementing messaging in such a solution is that the team is unlikely to work (as mentioned in the comments of @Gope).

This means that before sending a message on the client side, all validation checks must be performed.

Now, even when you perform a check on the client side, you can still encounter the conditions of the race - 2 users creating a party, at the same time conflicting with each other. The way to deal with this is to clarify the intention of the user, perhaps to change the nature of the task, as well as the user interface, so that the new team succeeds even in case of parallel processing.

As a simple blow to the solution, you can redefine the logic to introduce a new state for the batch type “conflicting” that will be set if another batch starts at the same time. Thus, the command succeeds (a package is created), and then you use something like SignalR to send a notification about this state to the user so that they can fix it.

Finally, you can completely redefine the use of messages and just move on to a simple two-tier synchronous solution. There is time and space for each approach.

+4
source

How to create these user interfaces for asynchronous messaging (especially after we were indexed into CRUD thinking) is a million dollar question in each of these systems.

I agree with the 100% Udi rating. In addition, your question seems rather opaque to specific business requirements, but the CRUD nature of the CreateBatch and BatchCreated events makes you wonder if this is really useful for messaging.

If you find yourself in a situation where you need to wait for the CreateBatch to complete so that you can do something else, you might not need to have CreateBatch. Maybe you just have to create something “locally” (this could mean the client side in JavaScript or, as Udi suggests, in the simplest two-tier database model), and then send a command to do the real work (maybe ProcessBatch?) as soon as everything is completed.

The goal of messaging, after all, is not to completely strip the web tier from database queries.

0
source

Source: https://habr.com/ru/post/969903/


All Articles