CQRS/ES and occasionally connected clients - more questions

339 views
Skip to first unread message

Mihai Ciureanu

unread,
Apr 5, 2013, 5:30:40 AM4/5/13
to ddd...@googlegroups.com
Hi,

I have been reading and watching the videos related to CQRS/ES in occasionally connected clients, and I have some questions

1. Greg talks about a "pending queue of commands" on the client, and the events which would have been produced if the commands were executed. Where are these events stored? I don't think they should be stored in the "normal" event store, because we must be able to remove them (along with the removal of a conflicting command for example) So I guess we should store the events in a pending queue/store of events, and change the repository to load events from the event store, and then apply the events from the pending queue/store in order to load the "current" aggregate. So the repository would be different from the server repository, because we don't have a pending queue on the server. Of course there could be some variations of this, for example embedding the events in the commands (since we already want to have some links) and storing them along with the commands in the pending commands queue.

Also, we might need to display somehow in the viewmodel whatever has been changed (like git plugins for explorer/visual studio do) - this would mean that anyway the event handlers which build the read models would have to know whether an event is commited or not for example. Would introducing a bool property like "IsPending" in all events make sense in this case? Since events are part of the domain, this would mean that the "IsPending" property is also part of the domain, does this make sense? Using this mechanism, we would have the command handlers load all events in order to build the current aggregate domain model, but having the handlers which build the read models decide whether to use the pending events or not. For example we could build a "server view", by filtering out all pending events. Does this make sense?

2. I also have some questions related to the process which executes after the merge has been done. So for example I have the list of new events from the server, I have the events generated by the pending commands, the client would for example delete a command which would conflict with some new events, and the new list of commands would be sent to the server. If the client gets a success reply (meaning that the commands were executed succesfully on the server) then it will get the events generated by the pending commands and store them in the event store. We know that we would have the same event store as the server, because we have the same domain logic and code on the client and on the server. But since this client is subscribed to this types of events to the server, the events would get to the client again if we don't filter them on the server or on the client. (I'm thinking that publishing an event to a "channel", but don't send it to a particular client subscribed to that channel sounds aliitle bit weird). So how would you do this?


3. How would you approach the next problem: I have just installed the smart client application and I start it. On the server there are already events which interest me, and I want to get them in order to build my domain model (for example some documents which I have already built using some other clients). The "persistant subscription" wouldn't help me in this case, because my client is subscribing only after the application has started the first time (or at least that's what I presume). So I need to download the events myself using other mechanism. If for example I want to download all documents which I have worked in the past, the server would have to query the read model and filter by OwnerId, and using all aggregates ids which he got from this query he will send me all the events with this aggregates id. Doesn't this have a smell already? Querying the read model since the client is only interested in events, and not read model? The read model could be stale for example. Or should we extend the Event Store to also include some information which could help us to get the events directly (like adding an OwnerId column). 


Sorry for the chaotic thoughts/questions and thanks in advance.

Daniel Lidström

unread,
Apr 5, 2013, 9:11:46 AM4/5/13
to ddd...@googlegroups.com
Hi Mihai!

From what I understand regarding occasionally connected clients (mainly from reading this list and searching the web), you don't have to filter any commands from the occasionally connected client. The server decides what to do when there is a conflict, but it doesn't remove any commands received from the clients.

A scenario might help explain things. Let's say a client is used to book seats. The client should accept any actions by the user, simply informing the user that the seat reservation *request* has been sent and is waiting confirmation. The server would not reject any "conflicting" commands. It doesn't have to. It can simply store both seat reservation request commands and decide which of them to grant. Then it can generate a conflict event for the one that is rejected, and a success event for the other. For the user this means all actions are always accepted. Only the consequence might change, depending on other user's actions.

The fact that you model your commands as SeatReservationRequest instead of SeatReservation would remove the need for IsPending property. It would be built into your domain already.

Does this make sense? Sorry if this doesn't answer all of your questions, it's just my understanding.

Greg Young

unread,
Apr 5, 2013, 9:15:07 AM4/5/13
to ddd...@googlegroups.com
Thats one way of doing it.


You run merges locally in the client before pushing (pushed means committed, local stuff is transient and can still be rejected)


--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Le doute n'est pas une condition agréable, mais la certitude est absurde.

Mihai Ciureanu

unread,
Apr 5, 2013, 9:56:14 AM4/5/13
to ddd...@googlegroups.com
HI Daniel,

Thank for the info. My application should be a simple collaborative working over a list of cars basically (adding cars, editting car information etc...). So the "git" solution proposed by Greg seems more fit for this kind of work - so merging on the client. Anyway, I'm still confused a little bit about having the same domain in both client and server. Since some commands are just in pending state on clients, while in server they are sure to be executed, there is a difference. Or maybe this is just a lower level difference, not in domain - it's something which is part of the command handlers, or event handlers. Also, there are some examples with commands which represent some real actions which have been done, so they cannot be removed or altered, so obviosly a "generic" merging solution cannot be proposed for every situation.

Greg Young

unread,
Apr 5, 2013, 9:57:32 AM4/5/13
to ddd...@googlegroups.com
you still send commands to the server domain not events.


--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Mihai Ciureanu

unread,
Apr 5, 2013, 9:58:17 AM4/5/13
to ddd...@googlegroups.com
Hi Greg,

Thanks for the answer. I have watched your presentation, thanks for that, and all my questions are related to that actually. Do you think my described process make sense?

Mihai Ciureanu

unread,
Apr 5, 2013, 10:04:18 AM4/5/13
to ddd...@googlegroups.com
So to refer to my first question, would you store the pending events in another place than the Event store?

Greg Young

unread,
Apr 5, 2013, 10:05:27 AM4/5/13
to ddd...@googlegroups.com
they are on the client.


--
You received this message because you are subscribed to the Google Groups "DDD/CQRS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Mihai Ciureanu

unread,
Apr 5, 2013, 10:13:27 AM4/5/13
to ddd...@googlegroups.com
Ok, but I understand the on the client you also have an event store which helps you build the aggregates, in the same way that you do on the server. So basically you have the event store from the server replicated on the client (or only the part the client is interested in). Is this correct?

In this case, would you store the pending events, which you use to create the "current" aggregate from the client point of view somewhere else?  "The events which would generate if the commands were to be executed" is not very clear for me. You actually execute the commands on the client first, right? Because you need to update the client read models so that offline work is possible. The only problem is that you want the events not to go to the event store, because you will not be able to remove them after this. Does this make any sense?

Greg Young

unread,
Apr 5, 2013, 10:15:20 AM4/5/13
to ddd...@googlegroups.com
If you call a file an "event store" sure :)

Mihai Ciureanu

unread,
Apr 5, 2013, 10:24:54 AM4/5/13
to ddd...@googlegroups.com
:) Ok, let me ask differently then: do you have two different files for commited (to server) events and pending events?

Greg Young

unread,
Apr 5, 2013, 10:26:33 AM4/5/13
to ddd...@googlegroups.com
yes ... the pending events are only in memory. They can be thrown away at any time.

the pending commands are stored in a separate file.

Mihai Ciureanu

unread,
Apr 5, 2013, 10:33:50 AM4/5/13
to ddd...@googlegroups.com
Ah ok, because the events can be deducted from the commands, so there is no need to store redundant information. That makes sense. So the mechanism with the repostory which gets the aggregate first from the event store file, and then applies the events from memory makes sense then? 




--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/f0et--D-8zU/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages