我有一个MassTransit saga状态机(派生自Automatonymous.MassTransitStateMachine),我正在尝试解决只有当我将端点配置prefetchCount设置为大于1的值时才会出现的问题。
问题是'StartupCompletedEvent'已发布,然后在saga状态持久保存到数据库之前立即处理。
状态机配置如下:
State(() => Initialising);
State(() => StartingUp);
State(() => GeneratingFiles);
Event(() => Requested, x => x.CorrelateById(ctx => ctx.Message.CorrelationId).SelectId(ctx => ctx.Message.CorrelationId));
Event(() => StartupCompleted, x => x.CorrelateById(ctx => ctx.Message.CorrelationId));
Event(() => InitialisationCompleted, x => x.CorrelateById(ctx => ctx.Message.CorrelationId));
Event(() => FileGenerationCompleted, x => x.CorrelateById(ctx => ctx.Message.CorrelationId));
Initially(
When(Requested)
.ThenAsync(async ctx =>
{
Console.WriteLine("Starting up...");
await ctx.Publish(new StartupCompletedEvent() { CorrelationId = ctx.Instance.CorrelationId }));
Console.WriteLine("Done starting up...");
}
.TransitionTo(StartingUp)
);
During(StartingUp,
When(StartupCompleted)
.ThenAsync(InitialiseSagaInstanceData)
.TransitionTo(Initialising)
);
// snip...!
当我的传奇收到请求事件时会发生什么:
此时,队列中没有消息,并且StartupCompletedEvent丢失。但是,数据库中有一个saga实例。
我在启动时玩过,并确定其他线程之一(因为我的预取是> 1)已经拾取了事件,没有在数据库中找到任何带有correlationId的传奇,并丢弃了该事件。因此,在传奇有机会被保留之前,该事件正在发布和处理。
如果我将以下内容添加到初始处理程序:
When(StartupCompleted)
.Then(ctx => Console.WriteLine("Got the startup completed event when there is no saga instance"))
然后我执行Console.WriteLine。我对此的理解是事件已被接收,但路由到初始处理程序,因为correlationId不存在传奇。如果我在这一点上设置一个断点并检查传奇回购,那么还没有传奇。
值得一提的是其他几点:
如果我遗漏了任何东西,请告诉我。我试图提供我认为值得的所有东西,而不会让这个问题太长......
答案 0 :(得分:2)
我也有这个问题,我想发布Chris的评论作为答案,以便人们可以找到它。
解决方案是启用发件箱,以便保留消息,直到保留saga。
c.ReceiveEndpoint("queue", e =>
{
e.UseInMemoryOutbox();
// other endpoint configuration here
}