簡體   English   中英

如何正確關聯啟動另一個控制器傳奇的多個實例的控制器傳奇?

[英]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基類上。

有兩種方法可以解決主要傳奇和不同發起者啟動子傳奇的問題。

  1. 使用兩個不同的命令。

讓兩個不同的命令啟動子傳奇,比如MySubProcessFromMainSagaCommandMySubProcessFromSomewhereElseCommand 可以為Saga提供多個IAmStartedByMessages<>

  1. 擴展MySubProcessCommand

MySubProcessCommand包含一些數據,以指示它是來自主要傳奇還是其他發起者。

無論哪種方式都會為您提供足夠的信息來存儲子傳奇的啟動方式,例如Data.WasInitatedByMainSaga 在子傳奇完成邏輯中檢查這一點。 如果是,請執行ReplyToOriginator()以與原始主傳奇進行通信。 如果沒有,請跳過回復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM