首页 文章

Nservicebus传奇超时

提问于
浏览
1

我有一个saga,如果从调用返回的状态成功,saga结束,则每隔30秒检查一次API调用的状态,如果不是saga等待30秒并再次尝试 . 如果API调用在60分钟内没有返回成功的响应,那么saga将超时并结束 .

我在解决60分钟超时问题时遇到了问题 . 我的代码是

public class MonitorSubmissionFeedSagaData: IContainSagaData
{
    public Guid Id { get; set; }

    public string Originator { get; set; }

    public string OriginalMessageId { get; set; }

    public bool TimeoutSet { get; set; }

    [Unique]
    public string JobId { get; set; }
}

public class MonitorSubmissionFeedSaga : Saga<MonitorSubmissionFeedSagaData>,
    IAmStartedByMessages<MonitorFeedSubmissonCommand>,
    IHandleMessages<StartCheckSubmissionCommand>,
    IHandleTimeouts<MonitorSubmissionFeedSagaTimeout>
{
    public const int SagaTimeoutInMinutes = 60;

    public IEmpathyBrokerClientApi PostFileService { get; set; }

    protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MonitorSubmissionFeedSagaData> mapper)
    {
        mapper.ConfigureMapping<MonitorFeedSubmissonCommand>(x => x.JobId).ToSaga(saga => saga.JobId);

    }

    public void Handle(MonitorFeedSubmissonCommand message)
    {
        Data.JobId = message.JobId;

        CheckTimeout();

        Bus.Send(new StartCheckSubmissionCommand
        {
            JobId = Data.JobId
        });
    }

    public void Handle(StartCheckSubmissionCommand message)
    {
        Log.Info("Saga with JobId {0} received", Data.JobId);

        bool isCompleted = GetJobStatus(message.JobId);

        while (isCompleted)
        {
            Thread.Sleep(30000);
            isCompleted = GetJobStatus(message.JobId);
        }

        MarkAsComplete();
    }

    public void CheckTimeout()
    {
        RequestTimeout<MonitorSubmissionFeedSagaTimeout>(TimeSpan.FromMinutes(SagaTimeoutInMinutes));
    }

    public void Timeout(MonitorSubmissionFeedSagaTimeout state)
    {
        MarkAsComplete();
    }

    bool GetJobStatus(string jobId)
    {
        return false;
        var status = PostFileService.GetJobIdStatus(jobId);
        if (status.state == "FAILURE" || status.state == "DISCARDED")
        {
            return false;
        }
        return true;
    }

}

任何人都可以看到我错在哪里?

谢谢

1 回答

  • 5

    你的传奇应该闲着 . 你通过while循环让它保持活力 . 超时消息到达某个时刻,然后您应该检查应该发生什么 . 另一个结账或MarkAsComplete .

    我在记事本中写了这个,所以它可能无法编译 . 但这是一个想法 .

    public class MonitorSubmissionFeedSagaData: IContainSagaData
    {
    public Guid Id { get; set; }
    public string Originator { get; set; }
    public string OriginalMessageId { get; set; }
    
    [Unique]
    public string JobId { get; set; }
    public DateTime SagaStartTimeUtc { get; set; }
    }
    
    public class MonitorSubmissionFeedSaga : Saga<MonitorSubmissionFeedSagaData>,
        IAmStartedByMessages<MonitorFeedSubmissonCommand>,
        IHandleTimeouts<VerifyApiTimeOut>
    {
    public IEmpathyBrokerClientApi PostFileService { get; set; }
    
    public void Handle(MonitorFeedSubmissonCommand message)
    {
        Data.JobId = message.JobId;
        Data.SagaStartTimeUtc = DateTime.NowUtc;
    
        CreateTimeoutRequest();
    }
    
    public void CreateTimeoutRequest()
    {
        RequestTimeout<VerifyApiTimeOut>(TimeSpan.FromSeconds(30));
    }
    
    public void Timeout(VerifyApiTimeOut state)
    {
        if (!GetJobStatus(Data.JobId) && DateTime.NowUtc < Data.SagaStartTimeUtc.AddMinutes(60))
        {
          CreateTimeoutRequest();
        }
    
        MarkAsComplete();
    }
    
    bool GetJobStatus(string jobId)
    {
        return false;
        var status = PostFileService.GetJobIdStatus(jobId);
        if (status.state == "FAILURE" || status.state == "DISCARDED")
        {
            return false;
        }
        return true;
    }
    
    }
    

    另一个评论可能是佐贺本身不应该呼唤外部服务 . 最好不要甚至某些数据库 . 将此委托给另一项服务 . 每隔30秒,向另一个处理程序发送一条消息 . 此处理程序应调用WebService / WebAPI . 当它可以确认一切正确时,回复原始的佐贺 . 当它不正确时,就让它成为现实 . Saga将每隔30秒发送一次消息进行重试 .

    60分钟后,Saga应该停止发送消息和MarkAsComplete .

相关问题