某些类型的异常的Nsb:跳过SLR +忽略错误队列的能力

时间:2016-10-24 18:28:26

标签: nservicebus

我希望有一个中心位置来为特定类型的异常实现异常处理逻辑。

如果发生特定的异常类型,我希望能够根据内部配置运行以下其中一项:

  • 立即将消息发送到错误队列而不再进行第二级重试;
  • 隐藏邮件,不将其发送到处理队列或错误队列;

我发现这个主题涵盖了第一个案例而不是第二个案例,因为如果我们返回TimeSpan.MinValue,消息将被置于错误队列中: NServiceBus error handling

那么我怎么能实施第二种情况呢?更好地在一个地方实施,一个类

1 个答案:

答案 0 :(得分:4)

在NServiceBus的第6版之前,您可以使用IManageMessageFailures来管理邮件失败。您可以处理序列化异常的情况,或者 - 与您手头的问题更相关 - 在尝试进行第一级重试后无法正常处理消息。

以下是如何实现自定义FaultManager,它忽略某些类型的异常,或将包含其他错误的失败消息发送回错误队列。请注意,仍然会发生第一级退役,而不是第二级重试。

public class IssueOrder : ICommand
{
    public bool NotFound { get; set; }
    public bool HasFaulted { get; set; }
}

public class OrderHandler : IHandleMessages<IssueOrder>
{
    public void Handle(IssueOrder message)
    {
        if(message.NotFound)
            throw new OrderNotFoundException();

        if(message.HasFaulted)
            throw new ApplicationException();
    }
}

public class OrderNotFoundException : Exception
{
}

public class CustomFaultManager : IManageMessageFailures
{
    private ISendMessages sender;
    private MessageForwardingInCaseOfFaultConfig config;
    private BusNotifications notifications;
    private static ILog Logger = LogManager.GetLogger<CustomFaultManager>();

    public CustomFaultManager(ISendMessages sender, IProvideConfiguration<MessageForwardingInCaseOfFaultConfig> config)
    {
        this.sender = sender;
        this.config = config.GetConfiguration();
    }

    public void SerializationFailedForMessage(TransportMessage message, Exception e)
    {
    }

    public void ProcessingAlwaysFailsForMessage(TransportMessage message, Exception e)
    {
        if (e is OrderNotFoundException)
        {
            //Ignore the exception;
            Logger.WarnFormat("OrderNotFoundException was thrown. Ignoring the message Id {0}.", message.Id);
        }
        else
        {
            //Check if you have performed enough retries, ultimately send to error queue
            SendToErrorQueue(message, e);
        }
    }

    private void SendToErrorQueue(TransportMessage message, Exception ex)
    {
        message.TimeToBeReceived = TimeSpan.MaxValue;
        sender.Send(message, new SendOptions(config.ErrorQueue));
        Logger.WarnFormat("Message {0} will was moved to the error queue.", message.Id);
    }

    public void Init(Address address)
    {
    }
}

注册自定义FaultManager:

var config = new BusConfiguration();
//Other configuration code
config.RegisterComponents(c =>
        {
            c.ConfigureComponent<CustomFaultManager>(DependencyLifecycle.InstancePerCall);
        });

然而,在NServiceBus的第6版中,不推荐使用IManageMessageFailures接口。版本6中的新Recoverability api允许更好的自定义,并且没有直接忽略/静音异常的方法。为此,您需要NServiceBUs pipeline中的自定义行为,并在其中一个已知步骤之间的步骤中运行(例如,在将消息移动到错误队列之前)。