2

使用 NServiceBus 4.3 我想在某些情况出现时向错误队列发送消息。

场景是,当我收到一条消息时,我检查这条消息是否指的是我们数据库中的 1 个或多个项目。如果有多个引用,我会抛出一个AmbiguousItemException并抓住它。我需要给负责给我正确信息的人发电子邮件。所有这些都已弄清楚,但我不希望再次尝试此消息。相反,我宁愿将它移到错误队列中,这样当我们取回我们需要的信息时,我们可以添加可空属性并将消息放回队列中进行处理。我试过使用_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);
4

2 回答 2

6

根据您的描述,听起来您有一个长期运行的业务流程。这是使用 Saga的候选对象。Sagas 像处理程序一样处理传入的消息,但 Saga 还允许您跟踪状态。因此,与其尝试将您的消息踢到错误队列中(这不是一个好主意),不如在 Saga 上设置某种类型的标志,例如布尔值或枚举,这将表明您收到了一条消息“如您所说,引用数据库中的 1 个或多个项目。

设置标志后,您可以触发某种消息来通知您或任何需要向您的客户发送电子邮件以获取更新信息的人(这可能是自动化的)。

一旦你收到必要的信息,你就可以采取任何必要的行动,然后向 Saga 发送一条消息,告诉它继续其进程和/或将其标记为完成并关闭它。

您可以在此处了解有关 Sagas 的更多信息

于 2016-07-06T02:08:25.840 回答
1

可以插入retires API 并返回一个“no retries”数字,本质上将某些异常发送到错误队列

http://docs.particular.net/nservicebus/errors/automatic-retries#second-level-retries-custom-retry-policy-exception-based-policy

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"];
    }
}
于 2016-07-07T07:43:10.373 回答