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

YMC*_*YMC 4 nservicebus

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

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

  • 立即将消息发送到错误队列,无需进一步的二级重试;
  • 隐藏消息,不将其发送到处理队列或错误队列;

我发现这个主题涵盖了第一种情况,但不包括第二种情况,因为如果我们返回,消息将被放入错误队列中TimeSpan.MinValueNServiceBus错误处理

那么我该如何实现第二种情况呢?最好两者都在一个地方、一个班级实施

Had*_*ari 5

在 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)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

并注册自定义FaultManager:

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

然而,在 NServiceBus 版本 6 中,该IManageMessageFailures接口已被弃用。版本 6 中的新可恢复性 API允许更好的自定义,尽管没有直接的方法来忽略/静音异常。为此,您需要在 NServiceBUs管道中自定义行为,并在已知步骤之一之间的步骤中运行它(例如,在将消息移至错误队列之前)。