2

I'm in researching phase of CQRS+ES. Never done in real world yet. But very soon.

However what I saw in StackOverflow and projects, CQRS seems to be fire and forget.

So what if there is a chain command which need result from another command.

First example, reward management and account management bounded contexts

  1. Application layer send GiveReward command to reward management

  2. Reward management fire a CreateTransaction command to account bounded context, And get the result as TransactionID(GUID). Refer to this answer, I can get the TransactionID while CQRS was fire and forget

  3. Reward management need to use some data of that transaction by query it from account management using TransactionID before fire next event.

Here how can I guarantee account management has finish creating read model, So that reward management can read it?

Second example, Rest API to open a Gacha box.

  1. User call this api.

  2. Application layer send OpenGacha command.

  3. Business layer fire and forget GachaOpenedEvent.

How can rest api guarantee OpenGachaEvent has created the read model?

These scenario lead me to a question,

Does CQRS need to be fire and forget, If we need to read guarantee after command?

Any others solution to solve this problem?

1

One way to view CQRS is that it's commands (messages) all the way down.

Taking your example:

  1. Application layer send GiveReward command to reward management with a correlation ID.
  2. Reward management fires a CreateTransaction command to the account bounded context, with the Correlation ID included.
  3. CreateTransaction finishes and broadcasts a TransactionCompleted event with the correlation ID.
  4. The Application Layer listens to TransactionCompleted events and connects it back to the original request through the correlation ID.

For your web front-end you can extend this approach to there as well. E.g. in a react/redux approach the command is relayed to the server, which eventually updates the redux store over a websocket feed which relays GiveRewardCompleted events.

Other approaches are returning the correlation ID to the front-end and have it poll the server for updates, or block at the server edge until a TransactionCompleted message is received.

1

Does CQRS need to be fire and forget, If we need to read guarantee after command?

CQRS doesn't need to be fire and forget. We typically acknowledge commands that cross process boundaries; it's a way of smoothing the mechanics of at-least-once delivery on a reliable network.

Here how can I guarantee account management has finish creating read model, So that reward management can read it?

There are usually two parts to the mechanic - one is some sort of correlation identifier that can be used to match results with the command, the other is a retry protocol.

At a meta level, you issue command(12345), and then you poll the reads, looking for resultOf(12345). The the read model hasn't been updated in a reasonable time, you resend the command; eventually if nothing good seems to be happening, you time out.

See also Nobody Needs Reliable Messaging.

0

No. This is a mix up of a few concepts. The single main point is that your underlying data model is not necessarily exposed in the same way for updates as read operations. There is nothing inherently "fire and forget" about this concept. Fire & forget comes in to play with asynchronicity which can apply (or not) regardless of how you carve up access to your data model.

If you need to guarantee a read returns data the takes into account one or more prior commands then by definition that command cannot * be fire & forget.

You can either get a point in time result and support F&F or you essentially serialise and wait until the update is complete. Of course this does not take into account the extra situation where other people/processes are performing updates between your commands and your reads.

*Unless you assume the outcome without waiting for confirmation which could cause more problems than it solves.

  • Well, that says that the problem is not restricted to CQRS (which is exactly what I thought when reading the question), but it does not give a solution. – Doc Brown Jun 17 '18 at 6:24
  • @DocBrown True, but the question is "Does CQRS really need to be fire and forget?" not a request for a solution, so I left it there. A solution would require understanding the problem at hand, and that's b.ben's job, not mine! – LoztInSpace Jun 17 '18 at 6:27
  • 1
    OK, I added request for the solution, So that others who face this can read. – b.ben Jun 17 '18 at 6:33
0

Yes, CQRS is about unidirectional communication only, that's true. And it is often used for asynchronous communication, which seems to be the core problem here (but even when CQRS is implemented in a synchronous manner, the caller may need to get a response if the transaction was successful or not).

The straightforward solution here is to make the system which retrieves and executes the command send an "acknowledge" message back to the caller, which signals success or failure of the transaction. The message is simply a command in the CQRS system, similar to the commands which initiate a writing transaction.

The caller then has to wait for that message (probably also in an asynchronous way) before he can proceed with actions which expect the transaction to be completed.

  • Good link. I think some of the early points in that article are what my answer was implying - write & read data models can be different without any asynch. – LoztInSpace Jun 17 '18 at 7:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.