使用NServiceBus 4.3我想在出现某些条件时向错误队列发送消息。
场景是当我收到消息时,检查此消息是否指的是我们数据库中的一个或多个项目。如果有多个引用,我会抛出一个AmbiguousItemException
并抓住它。我需要通过电子邮件向负责人提供正确的信息。所有这一切都被弄清楚,但我不希望再次尝试这条消息。相反,我宁愿将其移动到错误Queue,所以当我们收到我们需要的信息时,我们可以添加nullable属性并将消息放回队列进行处理。我尝试过使用_bus.ForwardCurrentMessageTo("error")
,_bus.Send("error", message)
,_bus.SendLocal(message)
。最后一个基本上将消息放在无限循环中。代码有点像这样。
public class MoveToErrorQueue
{
private readonly IBus _bus;
public MoveToErrorQueue(IBus bus)
{
_bus = bus;
}
public virtual void Send(ResubmitMessage message)
{
message.Foo= -1;
_bus.Send("error", message);
}
}
以及调用它的代码
try
{
//removed for brevity
}
catch (AmbiguousItemException ex)
{
Log.Error(ex);
sendNotificationCommand.FailureMessage = ex.Message;
_moveToErrorQueue.Send(commandMesage);
}
SendNotification(sendScanningNotificationCommand);
答案 0 :(得分:6)
从您所描述的内容来看,您的业务流程似乎很长。这是using a Saga的候选人。 Sagas处理传入的消息,如处理程序,但Saga也允许您跟踪状态。因此,不要试图将消息放入错误队列(这不是一个好主意),而是可以在Saga上设置某种类型的标志,如布尔值或枚举,这将表明您收到的消息是“引用数据库中的一个或多个项目“正如你所说的那样。
设置好标志后,您可以触发某种消息,通知您或者需要将电子邮件发送给您的客户以获取更新信息(这可能是自动化的)。
一旦您收到必要的信息,您可以采取任何必要的行动,然后将信息发送回Saga,告诉它继续其过程和/或将其标记为完整并将其关闭。
答案 1 :(得分:1)
可以插入退休API并返回"无重试"编号基本上将某些异常发送到错误队列
var retriesSettings = busConfiguration.SecondLevelRetries();
retriesSettings.CustomRetryPolicy(MyCustomRetryPolicy);
政策
TimeSpan MyCustomRetryPolicy(TransportMessage transportMessage)
{
if (transportMessage.ExceptionType() == typeof(MyBusinessException).FullName)
{
// Do not retry for MyBusinessException
return TimeSpan.MinValue;
}
if (transportMessage.NumberOfRetries() >= 3)
{
return TimeSpan.MinValue;
}
return TimeSpan.FromSeconds(5);
}
还有一个标题助手
static class ErrorsHeadersHelper
{
internal static int NumberOfRetries(this TransportMessage transportMessage)
{
string value;
if (transportMessage.Headers.TryGetValue(Headers.Retries, out value))
{
return int.Parse(value);
}
return 0;
}
internal static string ExceptionType(this TransportMessage transportMessage)
{
return transportMessage.Headers["NServiceBus.ExceptionInfo.ExceptionType"];
}
}