如何处理rebus传奇中的状态转换?

时间:2015-09-17 18:54:24

标签: rebus

我们假设我有一个包含以下值之一的状态的传奇数据:

JustWaiting, AwatingPrepareDrink, WaitingForPayment

我还要处理不同的消息,但只想在状态具有特定值时处理它们。

ie。:仅当状态为AwaitingPrepareDrink时处理PrepareDrinkMessage

为实现这一目标,我目前正在做类似的事情:

public async Task Handle(PrepareDrinkMessage message)
{
    if(Data.CurrentState != BaristaSagaData.State.AwatingPrepareDrink)
    {
        return;
    }

    //do some stuff...


    //state transition
    Data.CurrentState = BaristaSagaData.State.WaitingForPayment;
}

我采用这种方法的问题在于,传入的消息很可能很快收到了一点(工作者可能正在另一个处理器中工作,将转换到正确的状态)。

我试过替换它:

if(Data.CurrentState != BaristaSagaData.State.AwatingPrepareDrink)
{
    return;
}

用这个:

if(Data.CurrentState != BaristaSagaData.State.AwatingPrepareDrink)
{
    //too soon, try again in 10 seconds
    await _bus.defer(TimeSpan.FromSeconds(10), message);
    return;
}

然而,这导致saga修订版增加而另一个处理程序正在做一些工作。当另一个处理程序完成时,会发生并发异常,因为同时修订版本已增加。

还有其他方法可以阻止根据状态处理邮件吗?

有没有办法在不影响修订的情况下推迟邮件?

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我认为这是一个好主意,我把它添加到0.98.12,可以在几分钟内在NuGet.org上找到。

现在你可以改变

if (Data.CurrentState != BaristaSagaData.State.AwatingPrepareDrink)
{
    //too soon, try again in 10 seconds
    await _bus.Defer(TimeSpan.FromSeconds(10), message);
    return;
}

if (Data.CurrentState != BaristaSagaData.State.AwatingPrepareDrink)
{
    //too soon, try again in 10 seconds
    await _bus.Defer(TimeSpan.FromSeconds(10), message);
    MarkAsUnchanged();
    return;
}

让我知道它是否适合您:)

这将导致加载和更新saga数据的管道步骤跳过更新此特定的saga数据实例。