gpt4 book ai didi

c# - 如何正确关联启动另一个 Controller 传奇的多个实例的 Controller 传奇?

转载 作者:太空宇宙 更新时间:2023-11-03 23:09:29 26 4
gpt4 key购买 nike

我有一个 controller saga,它曾经有一个步骤来启动一个进程,该进程在一个事务中包含 3 个 Action 。我现在正在将这个子流程重构为一个单独的传奇。这样做的结果是,原始 saga 将启动新“sub-saga”的多个实例(此 sub-saga 也将由其他非 saga 进程通过相同的命令启动)。我的问题是如何以最好的方式关联这个传奇的层次结构?

在下面的示例中,主 saga 将尝试启动具有相同 correlationId 的 sub-saga 的三个实例。即使这行得通,这 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()在 sub-saga 中与 main saga 通信。该方法暴露在 Saga 基类上。

有两种方法可以解决由主 saga 和不同的发起者启动 sub-saga 的问题。

  1. 使用两个不同的命令。

让两个不同的命令开始子传奇,比如 MySubProcessFromMainSagaCommandMySubProcessFromSomewhereElseCommand .可以有多个 IAmStartedByMessages<>对于传奇。

  1. 扩展MySubProcessCommand

MySubProcessCommand 中包含一些数据以表明它是来自主要传奇还是来自其他发起者。

无论哪种方式都会为您提供足够的信息来存储 sub-saga 是如何开始的,例如 Data.WasInitatedByMainSaga .在 sub-saga 完成逻辑中检查这一点。如果是真的,做一个ReplyToOriginator()与最初的主要传奇进行沟通。如果没有,请跳过回复。

关于c# - 如何正确关联启动另一个 Controller 传奇的多个实例的 Controller 传奇?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39869916/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com