2015-11-19 3 views
1

У меня есть сага, которая проверяет статус вызова API каждые 30 секунд, если состояние, возвращенное обратно из вызова, успешно завершено, если не , сага ждет 30 секунд и снова пытается. Если вызов API не возвратил успешный ответ в течение 60 минут, сага вычеркнута и закончилась.Nservicebus saga timeout

У меня возникли проблемы с получением моего 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; 
    } 

} 

Может ли кто-нибудь увидеть, куда я иду не так?

спасибо

ответ

4

Ваша сага должна простаивать. Вы держите его в живых с циклом 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. Когда он сможет подтвердить, что все правильно, ответьте на оригинальную сагу. Когда это не правильно, просто позвольте этому быть. Сага будет отправлять сообщения каждые 30 секунд, чтобы повторить попытку.

Спустя 60 минут сага должна прекратить отправку сообщений и отмечать маркировку.

Смежные вопросы