2013-07-05 81 views
6

我們正在使用CQRS + ES。 ES是NEventStore(大概是JOliver EventStore)。我們有2個不同的命令集合。第二AR的投影取決於讀取模型中由第一AR投影寫入的數據。問題是,當我們運行軟件的時候,一切都變得非常快,以至於有時候這兩個聚合會被保存在具有相同日期時間的事件存儲(列CommitStamp)中。當重播事件時,我們從CommitStamp列開始按順序獲取它們。但是,如果這兩個流具有相同的CommitStamp並且採用錯誤的順序,則讀取的模型預測會有例外。NEventStore問題與重播事件

任何想法如何解決這個問題?

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

這裏是關於這個問題,在github上 https://github.com/NEventStore/NEventStore/issues/170討論

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

編輯:這就是我們目前正在重播​​事件。我搜索了GetFrom(...)的工作方式,結果是commitstamp列沒有用於排序。畢竟沒有提交命令。所以,如果我開始重放事件,可能從今天返回的事件,未來事件記錄2年前,旁邊等

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

這是[已知問題(#159)](https://github.com/NEventStore/NEventStore/issues/159);至少對於一些持久性後端來說。你使用哪個持久性引擎? – Marijn

+0

我們正在使用MSSQL 2008 – mynkow

+0

@Marijn:這正是我們的問題。 – mynkow

回答

1

Damian在數據庫中添加了檢查點列。這在當前的主分支中。當與GetFromCheckpoint(int)重播的事件結果是正確的。

0

在數據庫級別,而CommitStamp是精過濾,將CommitSequence列是一個應該指導訂購。

至於那這相當於在API調用方面對您正在使用的庫的任何版本 - 我會離開,作爲一個練習對你(或者,如果你在一個代碼段和/或填版本一提也許別人可以介入)

+0

我在Q上添加了我們正在嘗試重播事件 – mynkow

+0

@mynkow +1的方法,現在好多了。稍後會刪除這個...... –

3

在NEventStore,一致性邊界流。從版本3.2開始(如@Marijn提到的,issue #159),當通過所有持久性引擎從流中讀取時,CommitSequence列用於訂購CommitMessages(以及其中包含的EventMessages)。

事件消息排序是一個每個流保證。在流中沒有暗示的消息的排序。由於所選持久性引擎的某些方面而可能發生的任何實際排序都是偶然的,不能依賴。

爲了保證跨流訂貨會嚴重限制該庫的分佈式有利的方面。即使我們考慮這樣的功能,它也必須與所有支持的持久性引擎(包括NoSQL存儲)一起使用。

如果你正在練習領域驅動設計,其中每個流代表的總根源,你需要保證在2個或更多聚集訂貨,這點在你的領域模型設計問題。

如果你的預測需要合併來自多個源(流)值,你可以依靠訂貨細胞內源,但你必須是對訂購源間靈活。您還應該考慮重複消息的可能性,尤其是在通過外部總線或隊列重播時。

如果您嘗試使用時間戳(CommitStamp)接收端,這將是脆弱的重新排序多個流。時間戳具有固定的分辨率(毫秒,滴答等)。即使只有一位作家,事情仍可能「同時」發生。

+1

好的,但是你錯過了這裏的一些東西。想象一下,該域的設計應該如何正確工作。 AR之間的引用僅通過ID。但是,在重播流時,商店可能會首先返回當前創建的流,而下一個可能是5個月前創建的流。我不認爲這是正確的。 – mynkow

+0

@mynkow IDDD書鼓勵您只存儲參考AR的ID。如果您需要編寫跨多個聚合的代碼,請使用狀態機的傳奇,等待所有必需的事件到達。那麼創建多個聚合的順序並不重要。 –

+0

這是應用程序修復框架錯誤時不必要的複雜性。而這個bug已經解決了。查看最新的Damian提交。 – mynkow