NServiceBus UnitOfWork吞下某些异常并避免消息失败

时间:2014-03-20 15:53:25

标签: nservicebus unit-of-work

我有一个有趣的用例,其中某些异常类型表示“此消息不再有效且应该被忽略”,但此代码对Bus没有任何意识,以便调用{{1} }。

我讨厌像每个消息处理程序中都需要的try / catch块这样的样板代码。所以我开始实现一个UnitOfWork来处理和吞下异常,但我找不到告诉框架的方法“是的,这个代码生成了一个异常,但忘记了这一点并完成了事务。”

Bus.DoNotContinueDispatchingCurrentMessageToHandlers()不起作用。我尝试注入Bus.DoNotContinueDispatchingCurrentMessageToHandlers()并调用ITransport,但这导致整个宇宙爆炸。即使单步执行源代码,我似乎也不知所措。

请注意,很可能这是一个可怕的想法,因为假设实际上存在异常情况时没有异常将导致事务提交,导致谁知道有多少不明的未知副作用。因此,最好有一个方法仍然回滚事务但丢弃该消息。但我会对潜在的“是的我知道我在做什么,提交交易而不管异常”选项感兴趣。

3 个答案:

答案 0 :(得分:5)

从NServiceBus版本4.4开始,您可以通过在我们的处理程序管道中注入一个行为来控制它。

这让你控制哪些例外可以静音。

class MyExceptionFilteringBehavior : IBehavior<HandlerInvocationContext>
{
    public void Invoke(HandlerInvocationContext context, Action next)
    {
        try
        {
            //invoke the handler/rest of the pipeline
            next();
        }
        //catch specific exceptions or
        catch (Exception ex)
        {
            //modify this to your liking
            if (ex.Message == "Lets filter on this text")
                return;

            throw;
        }
    }

有几个样本如何运作:

http://docs.particular.net/samples/pipeline/

那就是说我完全同意拉蒙的观点,只有当你不能改变设计以避免这种情况时才应该使用这个技巧。

答案 1 :(得分:1)

一个肮脏的解决方案是让一个工作单元测试异常,将消息id放在一个共享&#39;忽略&#39; bag(内存中的并发字典,db,什么对你有用),让它失败以便一切都回滚,在重试时有一个通用的消息处理程序比较消息ID并让那个调用Bus.DoNotContinueDispatchingCurrentMessageToHandlers()

如果您不想使用某个工作单元,那么您可以尝试使用AppDomain.FirstChanceException。

我不会建议任何这些作为好的解决方案: - )

答案 2 :(得分:0)

你为什么要吞下&#39;未处理的例外?

如果你想忽略一个异常,那么你应该在处理程序中捕获这些异常,然后返回并记录它。

我更感兴趣的是国家呢?你可能已经写过商店了。不应该回滚这些写入吗?如果你吞下一个例外事务提交。

在我看来,你正在运行一种“至少一次交付”的方式。环境。那么你需要在某处存储某种消息ID。

或者这是一个基于陈旧状态的几个演员发起的行动?在这种情况下,您需要具有第一个/最后一个写入获胜结构,它只是忽略基于陈旧项目的命令。

如果您处理事件,则吞下异常似乎不正确。他们通常说你可以忽略命令,但你总是要处理事件。

这不应该是验证的一部分吗?如果验证命令,则可以决定忽略它。