我们正在尝试使用Saga序列化对业务对象列表的处理。
现在,没有Saga,我们只需遍历对象列表,然后触发bus.Send(new ProcessBusinessObejct(obj))
异步以使处理程序执行。因此,我相信根据此设置,处理或多或少并行进行。
endpointConfiguration.LimitMessageProcessingConcurrencyTo( 4 );
这很好,但是并发处理程序的数量现在很难在数据库上找到。
可以依次触发这些处理程序,即仅在当前进程完成(失败或成功)时才继续下一个处理程序。我们不想将并发设置为1,这会影响端点中的所有处理程序。
这个想法是使用Scatter / Gather模式和Saga来跟踪对象的数量,并使用一个计数(总计数,失败计数,成功计数)更新状态机,最后触发列表完成/为空时发生的事件。
问题是
A)我不确定如何在传奇中跟踪列表。 SagaData是否需要一个List来保留所有对象?然后,当处理程序发出信号表明已完成处理时,请删除该实例。 传奇不支持分层数据,因此不支持列表或列表。我相信在NSB v7中仍然如此。
然后B)使用英雄传奇是可行的还是过度杀伤力的,还是有一种更简单的方法来实现这一目标?
我们正在使用Sql Server持久性和传输以及NSB 7。
非常感谢任何输入!
答案 0 :(得分:1)
我认为您正在寻找这样做。注意,根据您使用的持久层,您可能需要将实际导入与更新saga状态分开。我已经对此here发表了博客。
传奇数据也可以存储列表,但是我认为在大多数情况下您都可以避免计数。另一个重要说明(尽管应该很明显)是,如果一条消息无法处理并进入错误队列(例如ImportData中未捕获的异常),则整个传奇将不完整,直到重试和处理该消息。>
public class MySaga : Saga<MySagaData>
: IAmStartedByMessages<StartTheProcess>,
IHandleMessages<ImportData>,
IHandleMessages<ImportFinished>
{
public async Task Handle(StartTheProcess message, IMessageHandlerContext context)
{
Data.ObjectsToImport = message.ObjectCount;
Data.JobID = Guid.NewGuid(); //To generate a correlation ID to connect future messages back to this saga instance
foreach(var id in message.ObjectIdsToImport)
{
await context.SendLocal(new ImportData
{
JobID = Data.JobID //You need this to correlate messages back to the saga
//Anything else you need to pass on to ImportData
ObjectIdToImport = id
}
});
}
public async Task Handle(ImportData message, IMessageHandlerContext context)
{
//import the data and increment the counter
var result = ImportData(message.ObjectIdToImport);
if(result == Result.Success)
{
Data.SuccessImport++;
}
else
{
Data.FailedImport++;
}
await CheckIfFinished(context);
}
public async Task Handle(ImportFinished message, IMessageHandlerContext context)
{
//do any post cleanups or Mark as complete
MarkAsComplete();
return Task.CompletedTask;
}
private async Task CheckIfFinished(IMessageHandlerContext context)
{
if(Data.SuccessImport + Data.FailedImport == Data.ObjectsToImport)
{
//Everything is done
context.SendLocal(new ImportFinished { JobID = Data.JobID });
}
}
}