Condivisione del flusso di origine degli eventi tra aggregati

2

Ho una domanda relativa a cqrs + sourcing di eventi. Ho due radici aggregate (AR1 e AR2). Quando AR1 ha ricevuto un comando / evento, verrà ricreato dal flusso di approvvigionamento dell'evento precedente dal repository (in questo caso avrà un elenco di alcuni valori x, y, z) e dopo aver aggiornato lo stato interno su (a, b, c, x, y, z) emetterà nuovi eventi (a, b, c). Questi eventi verranno recuperati da AR2 e quindi elaborati. Nel momento in cui ho bisogno di ricreare AR2 dal flusso di origine degli eventi, il livello tratteggiato all'interno di AR2 dovrebbe essere esattamente lo stesso di leyer all'interno di AR1 - quindi dovrei avere (a, b, c, x, y, z).

Un altro avviso: in AR2 questo layer sarebbe di sola lettura = necessario per fare qualche logica di business all'interno di AR2.

La domanda è: posso utilizzare gli stessi eventi generati nel livello interno AR1 per ricreare il livello tratteggiato AR2?

C'è sempre l'opzione per duplicare i dati (avere lo stesso flusso di eventi memorizzati sia nel livello AR1 che nel livello tratteggiato AR2) ma questo semplicemente sprecherà memoria. Un'altra opzione è sempre quella di inviare tutti i dati dal livello AR1 a AR2 ogni volta che accade qualche evento - in questo caso invierei anche x, y, z insieme a a, b, c.

[UPDATE] Mi è appena venuto in mente che posso modellare questo come AR2 facendo riferimento a AR1 e chiedendo AR1 ogni volta per i dati. Basta vedere come gestire questo caso poiché in CQRS l'aggregato non può restituire i dati?

Whataboutthisimplementationwithsagastylebelow?

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
        }
    }
}
    
posta Marko Kraljevic 30.08.2016 - 16:19
fonte

1 risposta

3

This events will be fetched by AR2 and then processed.

Ohh, sembra una cattiva idea.

One more notice - in AR2 this layer would be read-only = needed to do some business logic inside AR2.

Quindi guardando la tua immagine, AR2 sta scrivendo eventi (d, e, f), che dicono che AR2 non è di sola lettura - che è buono; leggere solo le radici aggregate non ha senso.

Il pattern solito per ciò che sembra si stia tentando di fare qui è usare un gestore dei processi per coordinare le attività delle due radici aggregate. Il ruolo del process manager è quello di ascoltare gli eventi e rispondere tramite i comandi di invio.

In questa immagine, avresti qualcosa di simile al seguente:

Command(A) arrives at AR(1)
    AR(1) loads its history [x,y,z]
    AR(1) executes Command(A), producing events [a,b,c]
    AR(1) writes its new history [x,y,z,a,b,c]

Events(a,b,c) are published

ProcessManager receives the events (a,b,c)
    ProcessManager dispatches Command(B) to AR(2)

Command(B) arrives at AR(2)
    AR(2) loads its own history [d,e,f]
    AR(2) executes Command(B), producing events [g,h]
    AR(2) writes its new history [d,e,f,g,h]

Events(g,h) are published

Cercare di avere due radici aggregate diverse in comune con una cronologia eventi comune è davvero strano; suggerisce strongmente che il tuo modello ha bisogno di un ripensamento (perché ci sono due diverse autorità per lo stesso fatto? Cosa succede quando AR1 scrive un evento che viola l'invariante applicato da AR2?).

Ma prendendo parte dello stato da un evento e trasformandolo in un argomento inviato a un altro aggregato; quel pattern è piuttosto comune. Il process manager stesso è solo un sostituto di un essere umano che legge gli eventi e decidere quali comandi attivare.

I always need current state of AR1 layer, even if AR2 is created from the scratch it needs to have content of layer from AR1. The layer would be read only.

Non esiste una cosa come ottenere lo stato "attuale" di un altro aggregato; AR1 potrebbe cambiare mentre AR2 sta facendo il suo lavoro, e non c'è modo di saperlo. Se ciò non è accettabile, i tuoi confini aggregati si trovano nel posto sbagliato.

Se i dati obsoleti sono accettabili, è possibile far sì che il gestore di comandi AR2 interroghi lo stato di AR1 e utilizzi tali informazioni nell'elaborazione del comando. Se lo farai, di solito preferisco racchiudere la query in un servizio di dominio, che ti offre un ulteriore livello di riferimento indiretto con cui lavorare (il modello di dominio non ha bisogno di sapere come è implementato il servizio). In questa progettazione, AR2 non vede affatto gli eventi AR1; AR2 passa alcuni stati al servizio di dominio e il servizio di dominio esamina gli eventi per capire la risposta e restituisce tale risposta come un valore che AR2 comprenderà.

La soluzione di Whittaker non è male ; una volta riconosciuto che i dati sono scaduti comunque , hai la possibilità di decidere se lo stato disponibile al momento della creazione del comando è abbastanza buono. Sono di menti miste su questo - mettere tutto nel comando è bello, e davvero facile da capire. D'altra parte, c'è una finestra più grande per una modifica che accada, e in una certa misura scoprire i dati giusti da usare richiede l'accesso allo stato interno all'aggregato che può cambiare mentre il comando è in volo.

Preferisco di gran lunga progetti in cui gli aggregati non sono accoppiati, però.

But it seems that this is again sharing of data between the AR-s, since fat command will use data from layer from AR1 to supply to AR2

Potresti esaminare ciò che Udi Dahan ha da dire su servizi come autorità tecniche . In quel caso, i dati che vengono condivisi sono per lo più limitati agli identificatori opachi.

    
risposta data 30.08.2016 - 16:48
fonte

Leggi altre domande sui tag