![](/img/trans.png)
[英]Is it possible to to correlate a message in MassTransit Saga that is not based on a ID?
[英]How to correctly correlate a controller saga which starts multiple instances of another controller saga?
我有一個控制器傳奇,它曾經在一個事務中啟動一個包含3個動作的進程。 我現在正在將這個子流程重構為一個單獨的傳奇。 這樣做的結果是原始的saga將啟動新的“sub-saga”的多個實例(這個sub-saga也將由其他非傳奇進程啟動,通過相同的命令)。 我的問題是如何以最好的方式關聯這種傳奇的層次結構?
在下面的示例中,主要傳奇將嘗試使用相同的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();
}
這個問題有“最佳實踐”解決方案嗎? 我一直在考慮使用Bus.Reply,當子傳奇完成時通知MainSaga。 問題是另一個消費者也在發送MySubProcessCommand而不等待已完成的事件/回復。
最佳做法是在子傳奇中使用ReplyToOriginator()
與主傳奇進行通信。 這種方法暴露在Saga基類上。
有兩種方法可以解決主要傳奇和不同發起者啟動子傳奇的問題。
讓兩個不同的命令啟動子傳奇,比如MySubProcessFromMainSagaCommand
和MySubProcessFromSomewhereElseCommand
。 可以為Saga提供多個IAmStartedByMessages<>
。
MySubProcessCommand
在MySubProcessCommand
包含一些數據,以指示它是來自主要傳奇還是其他發起者。
無論哪種方式都會為您提供足夠的信息來存儲子傳奇的啟動方式,例如Data.WasInitatedByMainSaga
。 在子傳奇完成邏輯中檢查這一點。 如果是,請執行ReplyToOriginator()
以與原始主傳奇進行通信。 如果沒有,請跳過回復。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.