NServiceBus6 задерживается восстановление не задерживается - PullRequest
0 голосов
/ 01 июня 2018

Не вдаваясь в подробности о проблеме, которую мы пытаемся решить, мне нужно заставить NServiceBus сделать 1 из 5 вещей, но сейчас я просто пытаюсь заставить работать первую.То есть, учитывая ответ на вызов веб-API, мы хотим сделать отложенную повторную попытку, немедленную повторную попытку, сдаться, отменить или начать заново.Отсроченная повторная попытка выглядит так, как будто это лучше всего сделать с использованием пользовательского восстановления, поэтому я следовал этому: Пользовательская политика восстановления и придумал это

public static class UpdateEndpointConfiguration
{
    public static void ConfigureEndpointForUpdateVocxoSurveyApi(this EndpointConfiguration configuration)
    {
        var recoverabilitySettings = configuration.Recoverability();
        recoverabilitySettings.CustomPolicy(SetCustomPolicy);
    }

    private static RecoverabilityAction SetCustomPolicy(RecoverabilityConfig config, ErrorContext context)
    {
        var action = DefaultRecoverabilityPolicy.Invoke(config, context);
        if (context.Exception is DelayedRetryException delayedRetryException)
        {
            return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(delayedRetryException.DelayRetryTimeoutSeconds));
        }
        return action;
    }
}

Затем в качестве теста я сделал простое сообщениепоэтому мне не нужно заставлять веб-API делать глупые вещи:

public class ForceDelayRetry : ICommand
{
    public int DelayInSeconds { get; set; }
}

, а затем «обрабатывать это»

public class TestRequestHandler : IHandleMessages<ForceDelayRetry>
{
    private static readonly ILog Log = LogManager.GetLogger(typeof(TestRequestHandler));

    public async Task Handle(ForceDelayRetry message, IMessageHandlerContext context)
    {
        Log.Info($"Start processing {nameof(ForceDelayRetry)}");
        var handleUpdateRequestFailure = IoC.Get<HandleUpdateRequestFailure>();
        await handleUpdateRequestFailure.HandleFailedRequest(new UpdateRequestFailed
        {
            DelayRetryTimeoutSeconds = message.DelayInSeconds,
            Message = $"For testing purposes I am forcing a delayed retry of {message.DelayInSeconds} second(s)",
            RecoveryAction = RecoveryAction.DelayRetry
        }, context, 12345);
        Log.Info($"Finished processing {nameof(ForceDelayRetry)}");
    }
}

Я запускаю службу и в промежуткепримерно через 1,5 минуты два тестовых сообщения были обработаны примерно 5400 раз.Сообщение журнала выглядит примерно так (пропущенная трассировка стека для краткости)

20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [22] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '690f317e-5be0-4511-88b9-a8f2013ac219' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '7443e553-b558-486d-b7e9-a8f2014088d5' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [4] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '690f317e-5be0-4511-88b9-a8f2013ac219' after a delay of 00:00:01 because of an exception:
20180601 15:28:47 :INFO  [14] TestRequestHandler Start processing ForceDelayRetry
20180601 15:28:47 :WARN  [14] NServiceBus.RecoverabilityExecutor Delayed Retry will reschedule message '7443e553-b558-486d-b7e9-a8f2014088d5' after a delay of 00:00:01 because of an exception:

, поэтому либо я делаю что-то не так, либо есть ошибка, но я не знаю, какая именно.Кто-нибудь может увидеть, в чем проблема?

edit

вот метод handleUpdateRequestFailure.HandleFailedRequest

    public async Task HandleFailedRequest(UpdateRequestFailed failure, IMessageHandlerContext context, long messageSurveyId)
    {
        switch (failure.RecoveryAction)
        {
            case RecoveryAction.DelayRetry:
                Log.InfoFormat("Recovery action is {0} because {1}. Retrying in {2} seconds", failure.RecoveryAction, failure.Message, failure.DelayRetryTimeoutSeconds);
                await context.Send(_auditLogEntryCreator.Create(_logger.MessageIsBeingDelayRetried, messageSurveyId));
                throw new DelayedRetryException(failure.DelayRetryTimeoutSeconds);
            case RecoveryAction.EndPipelineRequest:
            case RecoveryAction.RestartPipelineRequest:
            case RecoveryAction.RetryImmediate:
            case RecoveryAction.RouteToErrorQueue:
                break;
        }
    }

, и, как указано в комментарии, ябудет иметь бесконечную повторную попытку для моего сообщения, которое я тоже узнал, но вот обновленная логика для него

    private static RecoverabilityAction SetCustomPolicy(RecoverabilityConfig config, ErrorContext context)
    {
        var action = DefaultRecoverabilityPolicy.Invoke(config, context);
        if (context.Exception is DelayedRetryException delayedRetryException)
        {
            if (config.Delayed.MaxNumberOfRetries > context.DelayedDeliveriesPerformed)
                return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(delayedRetryException.DelayRetryTimeoutSeconds));
        }
        return action;
    }

1 Ответ

0 голосов
/ 05 июня 2018

То есть, учитывая ответ на вызов веб-API, мы хотим сделать отложенную повторную попытку, немедленную повторную попытку, сдаться, отменить или начать заново.Отсроченная повторная попытка выглядит так, как будто это лучше всего сделать с использованием пользовательского восстановления

Я не уверен, что понимаю, чего вы пытаетесь достичь, помимо того, что уже предлагает NServiceBus?Пусть немедленная и отложенная повторная попытка делает то, что лучше всего: делает фактическую повторную попытку.

А если вы хотите больше функциональности, используйте сагу.Позвольте саге организовать процесс и иметь отдельный обработчик для фактического вызова внешней службы.Затем сага, основываясь на ответах этого обработчика, может решить, следует ли ей остановиться, продолжить, выбрать альтернативный путь и т. Д.

Если вы хотите обсудить это дальше, я предлагаю вам связаться с нами по адресу support @ specific.net и мы можем установить конференц-связь и показать вам, как мы это сделаем.

...