我希望有一个中心位置来为特定类型的异常实现异常处理逻辑。
如果发生特定的异常类型,我希望能够根据内部配置运行以下其中一项:
我发现这个主题涵盖了第一个案例而不是第二个案例,因为如果我们返回TimeSpan.MinValue
,消息将被置于错误队列中:
NServiceBus error handling
那么我怎么能实施第二种情况呢?更好地在一个地方实施,一个类
答案 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中的自定义行为,并在其中一个已知步骤之间的步骤中运行(例如,在将消息移动到错误队列之前)。