I am using commanded in a project for 3 years now. So first of all: Thanks to the commanded team!
I have an aggregate that represents something similar like a company unit, that I have to close down.
The company unit has other aggregates linked to it. In this particular case it is hardware, that needs to be unregistered und users, that need to be removed from this company unit (revoking their permissions).
When I was implementing such cases in the past, I used simple event handlers. In this new story I wanted to have a closer look at process managers.
What I did not get is, how to start a process, so what is the first event to listen to and to start the process manager instance from?
Is it the CompanyUnitClosed event, that was emitted by the CompanyUnit aggregate after sending a CloseCompanyUnit command to it?
Or is it more like a CompanyUnitCloseProecssStarted event that I would need to directly add to the event stream?
How was it supposed to be used?
I hope someone can help me with this two approaches or even present a new one!
The aggregates that are attached to the Company, if they receive commands from sources other than the Company aggregate then you could have a race condition where you told the Company to close, and the Process manager turns to another aggregate to shut it down, but cannot or should not because it’s in the middle of its own workflow – if that workflow ever tried to call a command back on the closed Company, you might have some problems, especially if the event was billable or otherwise very important.
Non exhaustive list of options:
You just close up children aggregates even if they’re in the middle of something because… it’s fine in your case
The PM could handle these errors (upon calling child aggregate it gets back an unexpected response, perhaps it could reopen the company, or something.) In the meantime the company is closed and acts/is projected that way, but attached aggregates may be busy dealing with their own commands/events.
You set the company in a ‘closing’ state (like you suggested with CompanyUnitCloseProecssStarted) where the PM would finalize the shutdown, send a ‘complete’ command to the Company and then itself shutdown on a CompanyUnitCloseProcessCompleted -type event. This helps minimize the possible events/commands that children aggregates might be orchestrating before the Company is marked as ‘closed’.
The asyncness of the event sourced process can require complex solutions, and you can refactor the commands/events/processes in several ways each with their own failure modes. The main question is what guarantees do you need? That should drive your implementation.