2013-07-05 13 views
6

Stiamo utilizzando CQRS + ES. ES è NEventStore (ferventemente JOliver EventStore). Abbiamo 2 aggregati in diversi comandi. Le proiezioni del secondo AR dipendono dai dati scritti dalle prime proiezioni AR nel modello letto. Il problema è che quando eseguiamo il software tutto procede così velocemente che a volte i due aggregati vengono mantenuti nell'archivio eventi con lo stesso datetime (colonna CommitStamp). Quando riproduciamo gli eventi li otteniamo dall'inizio ordinato dalla colonna CommitStamp. Ma se i due flussi sono con CommitStamp identici e sono stati ripresi nell'ordine sbagliato, le proiezioni del modello di lettura soffiano con eccezioni.Problema NEventStore con eventi di riproduzione

Qualche idea su come risolvere questo problema?

===============================

Ecco la discussione su questo problema a github https://github.com/NEventStore/NEventStore/issues/170

===============================

EDIT: Questo è il modo in cui attualmente riprodurre gli eventi . Ho cercato come funziona GetFrom (...) e si è scoperto che la colonna commitstamp non viene utilizzata per l'ordine. Dopotutto non c'è un ordine di commit. Quindi, se inizio a riprodurre gli eventi si può restituire un evento a partire da oggi, il prossimo un evento registrato 2 anni fa, accanto ecc

public void ReplayEvents(Action<List<UncommittedEvent>> whatToDoWithEvents, DateTime loadEventsAfterDate) 
    { 
     var eventPortion = store.Advanced.GetFrom(loadEventsAfterDate); 

     var uncommitedEventStream = new UncommittedEventStream(); 
     foreach (var commit in eventPortion) 
     { 
      foreach (var eventMessage in commit.Events.ToList())) 
      { 
       uncommitedEventStream.Append(new UncommittedEvent(eventMessage.Body)); 
      } 
     } 
     whatToDoWithEvents(uncommitedEventStream.ToList()); 
    } 
+0

Questo è un [problema noto (# 159)] (https://github.com/NEventStore/NEventStore/issues/159); almeno per alcuni backend di persistenza. Quale motore di persistenza usi? – Marijn

+0

Stiamo utilizzando MSSQL 2008 – mynkow

+0

@Marijn: questo è esattamente il nostro problema. – mynkow

risposta

1

Damian ha aggiunto una colonna di checkpoint nel database. Questo è nel ramo master attuale. Quando gli eventi sono riprodotti con GetFromCheckpoint(int) i risultati sono corretti.

0

a livello di database, mentre il CommitStamp va bene per il filtraggio, la colonna CommitSequence è quella che dovrebbe guidare l'ordine.

Per quanto riguarda ciò che si traduce in termini di chiamate API su qualsiasi versione della librerie che si sta utilizzando, la lascerò come esercizio per te (o se inserisci uno snippet di codice e/o un menzione della versione che forse qualcun altro può intervenire)

+0

Ho aggiunto il metodo che stiamo sperimentando per la riproduzione degli eventi – mynkow

+0

@mynkow +1 sulla Q, molto meglio ora. Probabilmente lo elimineremo più tardi ... –

3

In NEventStore, il limite di consistenza è il flusso. A partire dalla versione 3.2 (come @Marijn menzionato, issue #159), la colonna CommitSequence viene utilizzata per ordinare CommitMessages (e in esso contenuto EventMessages) durante la lettura da uno stream su tutti i motori di persistenza.

EventMessage L'ordine è garantito su base per streaming. Non esiste alcun ordinamento implicito dei messaggi attraverso i flussi. Qualsiasi ordinamento effettivo che può verificarsi come conseguenza di alcuni aspetti del motore di persistenza scelto è accidentale e non deve essere invocato.

Per garantire che l'ordine attraverso i flussi limiterà severamente gli aspetti favorevoli alla distribuzione della libreria. Anche se dovessimo considerare una tale funzionalità, dovrebbe funzionare con tutti i motori di persistenza supportati, che include gli store NoSQL.

Se si pratica il Domain Driven Design, in cui ogni stream rappresenta una radice aggregata e occorre garantire l'ordine su 2 o più aggregati, ciò fa riferimento a un problema di progettazione nel modello di dominio.

Se le proiezioni necessitano di unire i valori da più fonti (flussi), è possibile fare affidamento sull'ordine intra-source, ma è necessario essere flessibili nell'ordinare l'inter-origine. È inoltre necessario tenere conto della possibilità di messaggi duplicati, soprattutto se si sta riproducendo tramite un bus esterno o una coda.

Se si tenta di riordinare più flussi sul ricevitore utilizzando un timestamp (CommitStamp), questo sarà fragile. I timestamp hanno una risoluzione fissa (ms, tick, ecc.).Anche con un singolo scrittore, le cose possono ancora accadere "allo stesso tempo".

+1

OK, ma ti manca qualcosa qui. Immagina che il dominio sia progettato come dovrebbe funzionare correttamente. I riferimenti tra AR sono solo per ID. Ma quando si riproducono i flussi, lo store può restituire prima uno stream creato oggi e il successivo potrebbe essere uno stream creato 5 mesi fa. Non penso che questo sia corretto in alcun modo. – mynkow

+0

@mynkow Il libro IDDD ti incoraggia a memorizzare solo ID di AR referenziati. Se è necessario scrivere codice che si estende su più aggregati, utilizzare una saga con una macchina a stati in grado di attendere fino a quando non sono arrivati ​​tutti gli eventi richiesti. Quindi l'ordine in cui vengono creati più aggregati non ha importanza. –

+0

Questa è una complessità non necessaria per l'applicazione per correggere un bug del framework. E questo bug era già stato risolto. Scopri gli ultimi impegni di Damian. – mynkow

Problemi correlati