我正在使用带有rebus.rabbitmq 3.0.0的rebus 3.1.5和rabbitmq.client 4.1.1。我已配置为使用简单的重试策略,最多2次传递尝试。我想在抛出异常的情况下重试该消息。我不使用事务范围。但是当抛出异常时,我不会再次重新传递消息(它甚至不在错误队列中)
如果这是不可能的,并且我需要使用HandleMessagesInsideTransactionScope配置rebus,它是否会锁定我的数据库,直到我完成处理程序工作?
非常感谢你!编辑:这就是处理程序的样子:
public Task Handle(SetCreditInfoCommand command)
{
return Task.Run(() => {
var loanApplication = _loanApplicationRepository.Get(command.LoanApplicationId);
try {
//something that throws an exception here
}
catch(Exception ex)
{
throw ex;
}
});
}
这就是总线的配置方式:
var bus = Configure.With(adapter)
.Transport(t => t.UseRabbitMq(connectionString, queueName))
.Options(b => b.SimpleRetryStrategy(
maxDeliveryAttempts: 2,
secondLevelRetriesEnabled: true,
errorQueueAddress: queueName + "_error"
))
.Timeouts(t => t.StoreInSqlServer(dbConnection, "RebusTimeouts", false))
.Start();
IoC.GetContainerBuilder().RegisterInstance(bus).As<IBus>();
答案 0 :(得分:1)
我不使用交易范围
好 - 只有当你想要将多个总线操作组合在一起的Rebus处理程序的外部时,才会出现事务范围。处理网络请求时。
Rebus处理程序中发生的一切都会自动组合在一起并作为跨越处理传入消息的事务上下文的一部分提交。
编辑:问题作者意味着System.Trasactions.TransactionScope
,Rebus可以使用Rebus.TransactionScopes包自动应用于邮件处理程序。
我最初认为它是RebusTransactionScope
,这是Rebus自己管理自己的消息传递事务的范围。
当抛出异常时我没有再次重新传递消息(它甚至不在错误队列中)
这听起来很奇怪。你是否让异常气泡退出了消息处理程序?
我将您的评论中的代码添加到您的问题中 - 以这种方式阅读更容易:)
首先,我建议您在方法声明中使用async
关键字来简化代码,如下所示:
public async Task Handle(SetCreditInfoCommand command)
{
// (...)
}
接下来,我建议您现在执行throw ex
,因为这不是正确的重新抛出 - 它会破坏ex
异常的堆栈跟踪。
你应该
catch(Exception ex)
{
throw;
}
如果您绝对想要捕获异常。但是我真的建议你不要在你的Rebus处理程序中捕获异常,除非你想对它们做些什么 - 在这种情况下,它看起来像你的处理程序会更好这样:
public async Task Handle(SetCreditInfoCommand command)
{
var loanApplication = _loanApplicationRepository.Get(command.LoanApplicationId);
//something that throws an exception here
}
因为它更清晰。
第二级重试工作正常,但立即重试无效
所以看起来Rebus直接跳到二级重试?你能告诉我更多关于你是怎么想出来的吗?