2

In ES/CQRS, do/can we treat requests as events?

Consider the following flow

A guest visited some url and posted data to create a new account. Here is one way to implement it

1- Invoke CreateNewUserCommand [payload = posted data]

2- Invoke CreateUserHandler(CreateNewUserCommand)

3- Fire CreateNewUserRequestedEvent [payload= posted data]

4a- Handle it in CreateNewUserEventHandler

4b- Validate the input against invariants 

5- If validation failed [invalid email, duplicate user, payment not sufficient etc] fire another event
UserCreationFailed:PaymentInsufficent [paylod= posted data]
UserCreationFailed:EmailInvalid [paylod= posted data]
UserCreationFailed:UserAlreadyExists [paylod= posted data]

6- If validation is successfull
fire an event
NewUserCtreated [payload= posted data + created user id]

Martin Fowler clearly states that we persist domain events when state is changed. Now if we consider CreateNewUserRequestedEvent, it is just an intention to change the state.

Later on when we replay the events, CreateNewUserRequestedEvent does not count as an event to take part in state update but NewUserCtreated event does.

However, if we look at the system externally, a request to do something [CreateNewUserRequestedEvent] is also an event. Take the example of a use case when we made the request, request got saved, but server goes down that instant.

Next time the server goes up, we can pick up from where we left and continue creating the user.

  • It sounds to me like you're describing a message queue. – Robert Harvey Aug 28 '18 at 3:49
2

In CQRS+ES there are domain events representing facts that are persisted instead of the flat state and commands that express the intent to do something that will result in zero or more facts. That being said, there is a difference between domain events, commands and infrastructure messages (like your "RequestEvent") in a message/event based architecture: domain events/commands are strongly related to the ubiquitous language, the domain, and the infrastructure messages are not, they only carry low level information.

The infrastructure messages can be the base for a nice, resilient message based asynchronous low level architecture, like the one that you are describing, that adds resilience to the application.

You should however treat differently the domain events/commands and the infrastructure messages, i.e. put them in different modules/namespaces, name them differently, or at least know the difference between them.

  • Agreed, I am definitely not talking about infra requests like http request stuff, it is more like Customer_Asks_To_Close_Her_Account type of commands which in natural language seems like a domain event request_to_close_account_by_customer_received. If we go down this path, then every command just triggers other events -> which start event handlers -> which might start more events -> and more handler. I can not see the commands as in real commands in this whole design. because every command is just a request that is a start point of event triggers. – Waku-2 Aug 28 '18 at 6:37
  • "then every command just triggers other events -> which start event handlers -> which might start more events" - this is how DDD Aggregates and Sagas work. But there is a difference between domain commands and domain events: commands express intent and events express facts. A command can fail (from the domain point of view) but an event never fails. – Constantin Galbenu Aug 28 '18 at 7:01
  • Both commands and events can be viewed as "messages", that travel from one "actor" to another, that can be persisted etc. – Constantin Galbenu Aug 28 '18 at 7:02
  • 1
    Thanks Constantin, I had the same impression but just wanted to make sure that I am doing it right because that seems like a natural confusion when you are doing something for the first time. – Waku-2 Aug 28 '18 at 7:24
1

In ES/CQRS, do/can we treat requests as events?

You can.

Usually what this means is that the decision to persist the event won't have any domain logic associated with it. The server just appends the information to a stream at whatever the current position happens to be.

The developers at LMAX published a lot of work describing the disruptor library; if you look carefully at how they use it, you'll see that a common case for them was that inputs were immediately (and sequentially) written into a journal, hot standbys used replicas of those journals to ensure that they were in the same state.

You may also want to look into ... an apostate's opinion, where Pat Helland talks about entities (using a somewhat different definition than the usual DDD/CQRS/ES spelling) and how they keep track of information that has been shared with them.

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.