I have a question related to cqrs + event sourcing. I have two aggregate roots (AR1 and AR2). When AR1 received a command/event it will be recreated from previous event sourcing stream from repository (in this case it will have list of some values x,y,z) and after updating internal state to (a,b,c,x,y,z) it will emit new events (a,b,c). This events will be fetched by AR2 and then processed. At the point when I need to recreate AR2 from event source stream, dashed layer inside AR2 should be excatly same as leyer inside AR1 - so there I should have (a,b,c,x,y,z).
One more notice - in AR2 this layer would be read-only = needed to do some business logic inside AR2.
The question is - could I use same events generated in AR1 inner layer to recreate AR2 dashed layer?
There is always option to duplicate data (have the same stream of events stored both in AR1 layer and in AR2 dashed layer) but this will just waste memory. Another option is always to send all the data from AR1 layer to AR2 whenever some event happens - in this case I would send also x,y,z together with a,b,c.
[UPDATE] It just came to my mind that I can model this as AR2 having reference to AR1 and asking AR1 each time for data. Just have to see how to handle this case since in CQRS aggregate cannot return data?
What about this implementation with saga style below?
Update: This is what I have so far - saga can be used for sending events transformed to commands from AR1 to AR2 (basically 2nd picture), but in case of instantiating new AR2 (green color in pic2 - that should not exist there actually), I do it from service layer like this:
namespace serviceLayer{
public void createAr1AndAr2(Ar1Id idar1, Ar2Id idar2){
var ar1 = getAr1FromRepo(iadr1);
var ar2 = getAr2FromRepo(idar2); //returns regularAr2 or nullObjectAr2
ar1.doSmth(ar2);
}
}
namespace domain{
class Ar1 {
List<Smht> partOfInnerState;
void doSmth(Ar2 ar2){
ar2.doSmth2(partOfInnerState);
}
}
class regularAr2 extends Ar2{
void doSmth(List<Smht> partOfInnerState){
//we need only part of partOfInnerState
}
}
class nullObjectAr2 extends Ar2{
void doSmth(List<Smht> partOfInnerState){
//we need full partOfInnerState in order to initialize this object for the first time
}
}
}