NServiceBus Saga多次处理消息类型会产生并发异常

时间:2014-11-05 12:17:11

标签: c# nservicebus bus saga nservicebus-sagas

我们有一个处理多种消息类型的NServiceBus实现:

public class StateCoordinator : Saga<MessageData>, 
                                IAmStartedByMessages<CreateMessage>, 
                                IAmStartedByMessages<ConfirmMessage>

MessageData是这样的:

public class FlowData : IContainSagaData
{
    [Unique]
    public Guid MappingId { get; set; }

    public Guid Id { get; set; }

    public string OriginalMessageId { get; set; }

    public string Originator { get; set; }

    public List<MessagePart> MessageParts { get; set; }
}

public MessagePart
{
    public int Id { get; set; }

    public string Status { get; set; }
}

CreateMessage有一个MessagePart,它被添加到其处理程序中的MessagePart中。 ConfirmMessage更新特定MessagePart的状态。

这是情景:

1)收到第一个CreateMessage。这在Raven中创建了Saga,并在MessageParts中添加了一个MessagePart(状态为#34; 1&#34;)。

2)收到第一个ConfirmMessage。这会将Saga中第一个添加的MessagePart的状态更新为&#34; 1 2&#34;。当转到RavenDB中的文档时,这在浏览器中是可见的。

3)收到第二个CreateMessage。这为MessageParts添加了第二个MessagePart。在查看数据时,第一个MessagePart的状态仍然是&#34; 1&#34;而不是&#34; 1 2&#34;这会引发并发异常(ActualETag不等于ExpectedETag):

A first chance exception of type 'Raven.Abstractions.Exceptions.ConcurrencyException' occurred in Raven.Client.Lightweight

Additional information: PUT attempted on document 'flow/79a7ee20-f090-4648-9b62-a3da00d87c93' using a non current etag

看起来每个消息类型都缓存了Saga数据。是这样吗?有解决方案吗?

注:

我们正在使用多个IAmStartedByMessages,但是当ConfirmMessage在CreateMessage之前时,则会将此消息添加到队列中,直到处理完CreateMessage。

1 个答案:

答案 0 :(得分:2)

经过几次测试后,我可以说没有真正的问题。我认为你无法解决并发异常(记录此异常),但是当发生此异常时,消息只是发送回队列进行重试。

我担心Handle的逻辑会被执行两次,但我想因为我启用了事务,所以情况并非如此。例如:其中一个操作是将消息发送到另一个总线以持久保存事件(perister-queue)。在异常发生之前调用此操作(在句柄之后,数据保存在Saga中并抛出异常)但是没有消息添加到persister-queue。重试成功的消息后(这会更新数据,因此不再存在并发异常),persister-message将添加到persister-queue。

结论:不是真正的问题,只是日志文件中的额外行。