Yoann CAPLAIN
Yoann CAPLAIN

Reputation: 121

can an entity within an aggregate move to another aggregate (same type) in Axon

Suppose we have an aggregate class A and has entity class B and entity class C, using event sourcing and AggregateMember with ForwardMatchingInstances.

2 aggregates A are created, with id aId1 and aId2.

We send a command to add a new entity of class B to aId1, with id bId1

We send a command to add a new entity of class B to aId1, with id bId2


Now for some reason we want to have one of the entity moved to another aggregate because the business logic has a specific logic for entity of type B (same for C).


Can axon support that? -> Can we move entity bId1 to aggregate aId2 without changing bId1 (keep same id, just move of aggregate).

To do that I would use a saga to make sure that:


What would happen for pending commands that were supposed to go to aId1 and do actions on bId1? (exception as not there anymore?)

Does new commands for bId1 are sent to aggregate aId2 after changes made (bId1 is now in aggregate aId2, with same entity id)?

Upvotes: 1

Views: 474

Answers (1)

Allard
Allard

Reputation: 2890

I think the only way to answer the question:

Can axon support that? -> Can we move entity bId1 to aggregate aId2 without changing bId1 (keep same id, just move of aggregate).

Is with a NO. And it's not because of Axon, but because of CQRS and Event Sourcing. You wouldn't want to emit Events containing state of entities in there. The only thing you have is a trail of "what happened" to your aggregate. What you need to do, is find out what the "move" really means, business-wise.

Implementation wise, you would typically see it as an add and delete (in whichever order). In case operations fail (perhaps add is invalid), you will need to be able to compensate for the failure. If failures are to be frequently expected, then yes, a "reserve-and-confirm" approach would be better than a "try-and-compensate" approach.

In Axon, you could either use a Saga or just use a controller. In the latter case, you just send a command and based on the result, send the second command. When the second command returns a failure, you can compensate the first.

Note that Commands are never "sent to entities". They are sent to an aggregate, based on the @TargetAggregateIdentifier annotated field (or whichever approach the CommandTargetResolver you configured may use). That field defines which aggregate instance is loaded. Then, once the Aggregate is loaded, Axon will define which entity within that Aggregate defines the handler to actually process the Command.

Final comment: very often, these situations depend on a lot of domain-specific details. It is very difficult to answer such a question sensibly without any information about the domain or case that you are building it for.

Upvotes: 2

Related Questions