Reputation: 1573
I have a question regarding the following situation. Let's say we have 2 domains with 2 aggregates. Domain A and domain B are different microservices.
In our design we decide that domain A don't have knowledge about domain B. In domain B each shop aggregate have a reference to one or more products (sellable items).
If we want to remove a product then we can send a RemoveProductCommand to domain A - product aggregate.
How to handle the update of the shop's where the items have to be removed from the sellable item list? We want to do this in a kind of "transactional" why (only mark as removed if it is also removed from all the shops).
I already thought about it and I see 4 possible options:
Listen in the shop aggregates to ProductRemovedEvent and then remove the product reference from the shop. Accept that this theoretical can result in situation where the product can't be removed and will be still on the shop selling list.
Create a SAGA in domain A and first remove items from shops before mark the product as removed. If the Saga processing failed then all the shop statussen should be restored by sending some restore commands to the already modified shop aggregates. To know which shop references to the product we use a query request to fetch that information.
Same as bullet 2 but store also shop information (id's) in the product aggregate (productListedInShopList).
Other domain/aggregate definitions (merge them for example)
Any suggestions what's the best way to solve this?
Upvotes: 1
Views: 194
Reputation: 661
I'm for option 2, but:
"A don't have knowledge about domain B": Option two promotes that B is upstream and A is downstream (A depends on B because A sends commands to B and A subscribes to events of B. This commands and events are part of the API of B), and not the other way around. But, this is fine! A and B are not mutually dependent.
Additionally, I would consider introducing the concept of Product in Domain B. For example, ShopProduct. This aggregate can be linked to your shops keeping the invariants safe (similar to your point number 3) within B domain model. This will decouple your bounded contexts: ShopProduct is how Shop bounded context understand this Product
concept. This will enable you to run only domain model B as an independent application as well.
ProductRemovedEvent would put Product (domain A) in some PENDING state, for example, REMOVING, and this event will trigger Saga
Saga would communicate between Product (domain A) and ShopProduct (domain B):
Upvotes: 3