2014-03-04 51 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事件已被处理并且一切都很好。

相关问题