Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CQRS and synchronous operations (such as user registration)

I'm in the process of adopting DDD concepts for designing our next projects, and more specifically CQRS.

After reading a LOT of stuff I'm now trying to implement a simple Proof Of Concept.

The thing is I'm stuck right after I started :p

I'm trying to apply this approach to a simple user registration process, where steps are:

  • User fills the registration form & submit the request
  • The app creates the user
  • The app authenticates the user (auto log in)
  • The app sends a verification email to the user
  • The app redirect the user somewhere else with a confirmation message

From an implementation point of view, what I get so far is:

  • The controller action maps the request data to a RegisterCommand object
  • The controller action asks the Command Bus to handle the RegisterCommand
  • The command handler (UserService) "register" method creates a new User object (whether by a new command or a factory object)
  • The model raises a RegisterEvent
  • The command handler asks the repository to store the new user object

That's it, the controller action doesn't know about any of that.

So, my guess is, since everything in this context HAS TO be done synchronously (except for the email sending), I can use a direct/synchronous command bus, and in the controller action, right after the command bus invocation, I can query for a read only User (query database) and if it exists assume that everything went well, so I can give the user a confirmation message.

The automatic log in process being handled by an Event Handler.

Assuming that this is correct, what if something goes wrong, how to inform the user with the correct information ?

A common example is often used in articles we can find over the internet: A customer pays his order by using an expired credit card. The system accepts the request, informs the user that everything is OK, but the user receives an email a few minutes later telling him that his order could not be processed.

Well, this scenario is acceptable in many cases, but for some other it is just not possible. So where are the examples dealing with these use cases ? :p

Thank you !

like image 977
Benjamin Avatar asked Apr 27 '13 09:04

Benjamin


People also ask

What is the use of CQRS?

Solution. CQRS separates reads and writes into different models, using commands to update data, and queries to read data. Commands should be task-based, rather than data centric.

What problem does CQRS solve?

CQRS is a popular architecture pattern because it addresses a common problem to most enterprise applications. Separating write behavior from read behavior, which the essence of the CQRS architectural pattern, provides stability and scalability to enterprise applications while also improving overall performance.

What is the difference between CQS and CQRS?

CQRS takes the defining principle of CQS and extends it to specific objects within a system, one retrieving data and one modifying data. CQRS is the broader architectural pattern, and CQS is the general principle of behaviour.

Is CQRS asynchronous?

Asynchronous commands are not required for CQRS.


1 Answers

I think this registration use case is closer to the paying for an order use case than you think.

Most of the CQRS thought leaders suggest validating on the read side before issuing a command, thus giving your command a higher probability of success.

If the validation fails on the read side, you know how to handle this - make the user pick another name before you even send off the registration command. If validation succeeds, send the command - now you're talking probably a few hundred microseconds AT MOST where another user could've come in and taken the same username between the time you validated the command and sent it off. Highly unlikely.

And in the very rare case when that does happen, you act in the same as way as the expired credit card example - the next time the user logs in, you present them with an explanation and a form to submit a new username - or send them an email saying "hey - someone else has that username, please click here to select a new one". Why does this work? Because you have a unique ID for that user.

Look at a user registration page like Twitter. As soon as you enter a username, it does a little Ajax call and says "nope, this is taken" or "this one is good!" That's pre-validation.

I hope this helps!

like image 172
Dan Avatar answered Sep 22 '22 15:09

Dan