0

I have a use case with two modules :

  • Users
  • Projects

I’m stuck with this use case :

At register, I have to check if Users mail is already associated to a user. If not, create the user and then create a Projects using the created user id.

I have a route like users/create.

How to avoid calling Projects create command inside Users create command ?

Do I have to use saga or may I miss some CQRS fundamentals ?

Alexy
  • 780
  • 6
  • 22

2 Answers2

0

In this case, I would use a Saga, because registering a user involves many steps, including things like:

  • Email validation,
  • Sending out welcome emails...
  • Checking for blocked users
  • Checking for duplicates

A single handler should not query the read side if you can avoid it. By delegating this task to a workflow, your simplify your aggregates/command-handlers.

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • That is what I'm thinking, by delegating to a workflow you mean like an upper-level orchestrator that call each route/command and so, move the logic in this orchestrator ? – Alexy Sep 14 '22 at 12:58
  • With a SAGA, I mean something in your architecture that runs in the backgrund perhaps listens for events when a new user tries to register, and then kicks off a workflow/process. Usually a user registration takes time ,like minutes or days (Between registration ,confirming email) , so it needs to be persisted to a database and survive when you redeploy your application. The user is not fully registered untill this process is completed. This is also a useful thing to detect fraud, abuse,... You usually want your command handle to be quick and not have to wait for to many things. – Tore Nestenius Sep 14 '22 at 13:25
  • This also simplifies error handling and many other things. – Tore Nestenius Sep 14 '22 at 13:26
0

In my experience, the simplest way to implement a solution for this would be to do what is minimally required in your command/handler, and then define an event handler which will do the subsequent processing needed. Event handlers can dispatch a command, that's a completely valid use case. Sagas are a tool for when you need to dispatch a particular command when multiple different events occur. In your scenario, if your application domain allows for it, I would use the register user command to validate the incoming data (such as email, making sure it's not used elsewhere), and then create the user record. Then, simply emit an event on the EventBus to the rest of the system that a user has been created, and have an event handler respond to that to create a Project record.

If your problem domain requires that a user cannot exist without a project, then you need to determine what level of consistency you need in your application. Is it acceptable for a user record to exist without a project record if it means that eventually the system will associate the user with a project? If so, then the above example would work well. But if you are in a circumstance where it's a requirement for the user to always be associated with a project, then you need strong consistency and should create both in your register user command.

The answer is subjective to your individual application's requirements. I would just encourage you to generally opt for handling things in your event handlers, and then reach for Sagas when you find yourself with multiple event handlers doing the same thing for different events. That's the use case for a Saga, when event X, Y, or Z occur, dispatch command A.

Good luck!

Daedalus
  • 36
  • 1
  • 5