如何正确关联启动另一个控制器传奇的多个实例的控制器传奇
本文关键字:传奇 控制器 实例 何正确 关联 另一个 启动 | 更新日期: 2023-09-27 18:11:47
我有一个控制器传奇,它曾经在一个事务中有一个步骤启动一个包含3个动作的流程。我现在正在将这个子过程重构为一个单独的传奇。这样做的结果是,原始的传奇将启动新"子传奇"的多个实例(该子传奇也将由其他非传奇进程通过相同的命令启动)。我的问题是如何以最好的方式将这些传奇的等级联系起来?
在下面的示例中,主传奇将尝试启动具有相同correlationId的子传奇的三个实例。即使这是有效的,3个实例也会通过处理来自所有实例的"完成事件"而相互干扰。
public class MyMainSaga : Saga<MyMainSagaData>,
IAmStartedByMessages<MyMainCommand>,
IHandleMessage<MySubProcessCommandCompletedEvent>
{
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MyMainSagaData> mapper)
{
mapper.ConfigureMapping<MyMainCommandCompletedEvent>(message => message.CorrelationId).ToSaga(data => data.CorrelationId);
}
public void Handle(MyMainCommand message)
{
Data.CorrelationId = message.CorrelationId;
foreach (var item in message.ListOfObjectsToProcess)
{
Bus.Send(new MySubProcessCommand{
CorrelationId = Data.CorrelationId,
ObjectId = item.Id
});
}
}
public void Handle(MySubProcessCommandCompletedEvent message)
{
SetHandledStatus(message.ObjectId);
if(AllObjectsWhereProcessed())
MarkAsComplete();
}
}
public class MySubSaga : Saga<MySubSagaData>,
IAmStartedByMessages<MySubProcessCommand>,
IHandleMessage<Step1CommandCompletedEvent>,
IHandleMessage<Step2CommandCompletedEvent>,
IHandleMessage<Step3CommandCompletedEvent>
{
protected override voidConfigureHowToFindSaga(SagaPropertyMapper<MySubSagaData> mapper)
{
mapper.ConfigureMapping<Step1CommandCompletedEvent>(message => message.CorrelationId).ToSaga(data => data.CorrelationId);
mapper.ConfigureMapping<Step2CommandCompletedEvent>(message => message.CorrelationId).ToSaga(data => data.CorrelationId);
mapper.ConfigureMapping<Step3CommandCompletedEvent>(message => message.CorrelationId).ToSaga(data => data.CorrelationId);
}
public void Handle(MySubProcessCommand message)
{
Data.CorrelationId = message.CorrelationId;
Data.ObjectId = message.ObjectId;
Bus.Send(new Step1Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step1CommandCompletedEvent message)
{
Bus.Send(new Step2Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step2CommandCompletedEvent message)
{
Bus.Send(new Step3Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step3CommandCompletedEvent message)
{
Bus.Publish<MySubProcessCommandCompletedEvent>(e => {
e.CorrelationId = Data.CorrelationId;
e.ObjectId = Data.ObjectId;
});
MarkAsComplete();
}
}
我看到的唯一解决方案是更改子传奇以生成一个单独的correlationId,并保留原始id。例句:
public void Handle(MySubProcessCommand message)
{
Data.CorrelationId = Guid.NewGuid();
Data.OriginatorCorrelationId = message.CorrelationId;
Data.ObjectId = message.ObjectId;
Bus.Send(new Step1Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step1CommandCompletedEvent message)
{
Bus.Send(new Step2Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step2CommandCompletedEvent message)
{
Bus.Send(new Step3Command{
CorrelationId = Data.CorrelationId;
});
}
public void Handle(Step3CommandCompletedEvent message)
{
Bus.Publish<MySubProcessCommandCompletedEvent>(e => {
e.CorrelationId = Data.OriginatorCorrelationId;
e.ObjectId = Data.ObjectId;
});
MarkAsComplete();
}
这个问题有"最佳实践"解决方案吗?我一直在考虑乘公交车。回复,当子传奇完成时通知主传奇。这样做的问题是,另一个消费者也在发送MySubProcessCommand而没有等待完成的事件/回复。
最佳实践是在子传奇中使用ReplyToOriginator()
与主传奇通信。此方法在Saga基类上公开。
有两种方法可以解决由主传奇和不同的发起者启动子传奇的问题。
- 使用两个不同的命令
让两个不同的命令启动子传奇,如MySubProcessFromMainSagaCommand
和MySubProcessFromSomewhereElseCommand
。一个Saga可以有多个IAmStartedByMessages<>
。
- 扩展
MySubProcessCommand
在MySubProcessCommand
中包含一些数据,以表明它是来自主saga还是其他发起者。
这两种方式都会给您足够的信息来存储子传奇是如何开始的,例如Data.WasInitatedByMainSaga
。在子传奇完成逻辑中检查这一点。如果为真,执行ReplyToOriginator()
以与原始主saga通信。