2014-03-04 50 views
2

我有兩種類型的事件:有條件啓動佐賀

  • PersonChanged
  • PersonAddressChanged。

當創建新人(和新地址)(創建或更新類型)時,他們兩個都正在發佈。

當創建一個新的人兩個事件公佈:PersonChanged和PersonAddressChanged(按順序)。但是,因爲NServiceBus是異步的,所以它們可以按任意順序處理。並且,當地址更改(對於現有人員)時,不存在PersonChanged事件,只有PersonAddressChanged事件。

我想寫PersonAddressChanged事件的處理程序,這將:

  1. 檢查,如果該人是在數據庫
  2. 如果是的話那麼就進行更新
  3. 如果沒有再啓動的傳奇,等待PersonChanged事件(假設它是一個新的人)

而在PersonChanged事件中,我需要插入的人的數據庫,找到傳奇和運行處理程序PersonAddressChangedØ再次。

我可以用NServiceBus傳奇故事實現這一目標?我不能認爲消息處理的順序應該是PersonChanged → PersonAddressChanged,因爲有時候不會有任何特定地址更改的PersonChanged事件。

回答

1

可以與傳奇,是做到這一點,雖然你可能不應該。首先,在創建和更新時都有相同的事件,在事件中失去了語義信息(這是您試圖通過檢查數據庫中的用戶來重新創建的)。你也讓自己接觸到很多潛在的競爭條件,並且需要考慮如何處理它們。我的建議是修改你的消息流,這可能會讓你目前的問題消失。

但是,如果你想反正試試,你會做這樣的事情:(未測試或編譯的,只是概念上的代碼)

public class MySaga : Saga<MySagaDataType>, IAmStartedByMessage<PersonChanged>, IAmStartedByMessage<PersonAddressChanged> { 
    public override void ConfigureHowToFindSaga() { 
     // How to correlate PersonChanged and PersonAddressChanged messages 
    } 
    public void Handle<PersonChanged>(PersonChanged msg) { 
     Insert(msg); 
     if(Data.PendingAddressChange != null) 
      UpdateDatabase(msg); 
     MarkAsComplete(); 
    } 
    public void Handle<PersonAddressChanged>(PersonAddressChanged msg) { 
     if(IsInDatabase(msg.Person)) { 
      UpdateDatabase(msg); 
      MarkAsComplete(); 
     } 
     else { 
      Data.PendingAddressChange = msg; 
     } 
    } 
} 
public class MySagaDataType : IContainSagaData { 
    public PersonAddressChanged PendingAddressChange { get; set; } 
} 
+0

我喜歡這個解決方案,但我得到以下錯誤:'NHibernate.Event.Default.AbstractFlushingEventListener-無法與會話NHibernate.PropertyValueException同步數據庫狀態:爲Namespace.PersonSaga.PendingAddressChanged ---> System.IndexOutOfRangeException脫水屬性值出錯:該計數= 29'的SqlParameterCollection的索引29無效。有任何想法嗎? – bpiec

+0

@bpiec:你的事件是作爲接口還是具體類來實現的? NServiceBus生成圍繞接口的代理類,NHibernate可能不喜歡。嘗試用該類的內容替換PersonAddressChanged屬性(即,如果'Person PersonAddressChanged {public string Address {get; set;} public Guid PersonId {get; set;}}',然後將這兩個參數移入' MySagaDataType'並將它們分開設置) – carlpett

+0

我在Saga類中添加了多個屬性,每個屬性都包含相同名稱的屬性,NSB在SQL Server中生成錯誤的表,然後無法保留傳奇:(無所謂,我會盡力找到解決方法,但答案是我正在尋找! – bpiec

2

我與@ carlpett的說法重新思考一些你的事件周圍的語義。

我也建議你考慮比這裏一個傳奇不同的解決方案。

如果你的PersonAddressChanged消息處理程序,當它看到數據庫中沒有當前的人,只是去創建一個具有它的地址的地址呢?

+0

事實上,我有單獨的事件添加和更改,但我不能假設,當更改地址我已經有一個人在數據庫中... – bpiec

+0

我不能創建一個新的人,它必須通過驗證和一些領域是必需的 – bpiec

+0

然後@ chrisbednarski的答案是我的建議。 –

1

如果PersonAddressChanged事件只發送給現有的人,我根本不會打擾傳說。

相反,我會依靠重試邏輯來處理不按順序到達的消息。

PersonAddressChanged處理任何時候,它可能會認爲一個人的記錄存在。如果它不是(即消息正在亂序處理),處理程序將拋出一個異常並稍後重試。

當它再次被重新處理時,PersonChanged事件已被處理並且一切都很好。

相關問題