0

So I'm a bit new with CQRS (not totally a beginner though). I'm trying to understand the best practices when it comes to aggregates interaction. I read a bit about using Integration Events (instead of Domain Events) in these situation, also a bit about Domain Services (that would supposedly link the 2 aggregates) but couldn't find any good definitive answer anywhere (especially not on the axonIQ Getting Started guide

Also another not too related question is that in layered architecture usually we have the controller directly linked to a service and this service can interact with other services (or repos) while with CQRS the controller is usually sending a command to the aggregate. So if my api call needs to interact with 2 aggregates do I have to build a middle-man service that would send commands (or listen to events) from the 2 services?

Ali_Nass
  • 838
  • 1
  • 9
  • 27
  • What is 'especially' wrong about the Getting Started guide in your opinion, @bleh10? If you have any recommendations on how to improve this, would you mind sharing that on the Reference Guide issue tracker? https://github.com/AxonIQ/reference-guide/issues – Steven Mar 26 '19 at 08:32
  • Nothing exactly is wrong, it's just that everyone around was mentioning domain services and integration events to solve related issues but I found nothing related to them in the Getting Started Guide which I personally found weird. – Ali_Nass Mar 26 '19 at 08:54
  • Alright, fair point there. If, whilst you're in the process of learning/using Axon Framework/Server do encounter pointers you dearly miss from the guide, please do add issues to the repository I've shared! We're always looking to improve our documentation to help out the users of Axon as much as we can. – Steven Mar 27 '19 at 09:28

2 Answers2

2

The interaction between components in a CQRS system can happen on a couple of levels. On way to think about it is as Maxime suggest, with Microservices, very clearly showing the messaging focus of it all.

Regardless though, this can just as simply happen within one Application/Monolith which has several Aggregate types that together need to trigger some operation.

I feel that Maxime is providing you the answer you need. The Aggregate instances which you send commands to, act on their own and do not tie in to one another directly, at all. You'd thus react on the events as the driving force the start an interaction between both.

You can either do this by having a Event Handling Component which listen to both the events and performs the business transaction you're dealing with. If the business transaction is a little more complex, looking at Saga's might be a good start.

Lastly, you state the 'Getting Started' part of the Axon Reference Guide is not clear about this topic. I think that's a valid conclusion, as from Axon's perspective this is not part of the Getting Started. Take a look at the Saga portion of the guide to get an idea of the interaction between Aggregates and/or Bounded Contexts.

Steven
  • 6,936
  • 1
  • 16
  • 31
  • 1
    Thank you for reply (on this and the other post) really appreciated! What Maxime said does help me achieve what I'm looking for. You do have a point that this is beyond the Getting Started guide. I will take a closer look (as I have only a general idea to what Sagas are) – Ali_Nass Mar 26 '19 at 08:59
  • That is great to hear! I do hope the guide helps you sufficiently on this part and if not, please share that if you have the time! – Steven Mar 27 '19 at 09:29
  • I'm sorry to annoy you here but I have [this](https://stackoverflow.com/questions/55480321/setting-up-mongo-extension-for-axon-framework-on-spring-boot) issue as well related to setting up mongo (config) with axon and would be glad if you can help us out! – Ali_Nass Apr 05 '19 at 08:12
  • No worries @bleh10, I actually think it's an honor you're searching me out to help on other issues as well! I've responded on the question you've shared just now. Let me know, over there, whether it helps you out! – Steven Apr 12 '19 at 08:13
1

If you think of this in term of microservices (which is a philosophy that fits CQRS very well) you should have one aggregate for one microservice. So you can't communicate between aggregates in memory because they're not part of the same process. A good way to do it is by using events that you can publish in a event bus. So the client send a command to "aggregate A" using the API of this microservice (i.e. "microservice A") (or maybe an API gateway). Then "aggregate A" is saved and the events generated by "aggregate A" are published to the event bus so that some process (aka. event handler) in "microservice B" can catch the event(s) and send the appropriate commands to "aggregate B".

It's just one way to do it there is many more and it can be very more complex than that, but I hope it's helping getting the big picture.

Maxime Gélinas
  • 2,202
  • 2
  • 18
  • 35
  • Is it good practice to send commands from one microservice to another one? Or is it better to have an event handler on microservice B that reacts to events from service A and generates the command all within the microservice B? – Ali_Nass Mar 26 '19 at 09:31
  • Events are really the best option here, because a microservice should work fine without the others (i.e. in this case not waiting for a response) It's one of the fundamentals rules of microservices. In some cases you can't do it with events and have to use a command directly, but it should be avoided if possible. If you really have to use a command send it through a message queue (aka. bus) so the sender don't have to know the exact location of the receiver. – Maxime Gélinas Mar 26 '19 at 13:32
  • I'd personally state that it is fine to share commands, events and queries among your services, as long as you do this consciously. The commands you'd handle on an application are really part of that service's API, just as the queries. On the other hand, the events a (micro)service publishes are also part of the API of that service. I'd thus not be so bold to state sending commands from one service to another is a no go. – Steven Mar 27 '19 at 09:30