有没有办法指定重试邮件的等待时间?

时间:2014-08-12 21:57:34

标签: rebus

有没有办法指定为特定异常重试邮件的等待时间?

E.g。如果object处于SomethingInProgress状态,则抛出SomethignInProgressException,我希望消息在40m后重试。或者更适合引发SomethingInProgressEvent并使用bus.defer?

2 个答案:

答案 0 :(得分:5)

这就是为什么Rebus没有second-level retries概念的部分原因 - 我根本没有看到任何方式可以以通用且足够灵活的方式创建此功能。

很快回答你的问题:不,没有(内置)方式来改变特定异常的重试之间的时间。事实上,在所有重试之间无法配置等待时间 - 失败的消息将尽可能快地重试,然后如果他们不能避免则会移动到错误队列"堵塞管道"。

在你的情况下,我建议你做这样的事情:

public void Handle(MyMessage message) {
    var headers = MessageContext.GetCurrent().Headers;
    var deliveryAttempt = headers.ContainsKey("attempt_no") 
        ? Convert.ToInt(headers["attempt_no"]) 
        : 0;

    try {
        DoWhateverWithThe(message);
    } catch(OneKindOfException e) {
        if (deliveryAttempt > 5) {
            bus.Advanced.Routing.ForwardCurrentMessage("error");
            return;
        }

        bus.AttachHeader(message, "attempt_no", deliveryAttempt + 1);
        bus.Defer(TimeSpan.FromSeconds(20), message);
    } catch(AnotherKindOfException e) {
        if (deliveryAttempt > 5) {
            bus.Advanced.Routing.ForwardCurrentMessage("error");
            return;
        }

        bus.AttachHeader(message, "attempt_no", deliveryAttempt + 1);
        bus.Defer(TimeSpan.FromMinutes(2), message);
    }
}

我刚刚写下了我的头脑而没有百分之百地确定它实际上是在编译...但是它的要点是我们跟踪我们在自定义标题中进行了多少次传递尝试消息,bus.Defer为每个失败的传递尝试拨打适当的时间跨度消息,当超过我们的最大传递尝试次数时立即将消息转发到错误队列。

我希望这是有道理的:)

答案 1 :(得分:0)

最近一个如何做到这一点的例子是:

public async Task Handle(IFailed<MyMessage> message)
{
    var maxAttempts = 10;
    var optionalHeaders = new Dictionary<string, string>();
    if (message.Headers != null && message.Headers.ContainsKey("attemptNumber"))
    {
        // increment the attempt number
        var attemptNumber = int.Parse(message.Headers["attemptNumber"]);
        attemptNumber++;
        optionalHeaders.Add("attemptNumber", attemptNumber.ToString());
        if (attemptNumber > maxAttempts)
        {
            // log I give up message, message will move to dead queue
            return;
        }
    }
    else
        optionalHeaders.Add("attemptNumber", "1");

    // if message failed to process, defer processing for 5 minutes and try again
    await Bus.Defer(TimeSpan.FromMinutes(5), message.Message, optionalHeaders);
}