Axon 分离轴突命令及其效果

Axon 分离轴突命令及其效果,axon,Axon,我正在维护一个源于事件的应用程序,恐怕它已经偏离了正轨 在一种情况下,聚合根收到一个命令,该命令发布一个事件,该事件由一个事件处理程序处理,该事件处理程序需要做两件事: 将命令(cmd1)发送到另一个聚合根目录,该聚合根目录将发布一个事件,该事件将在每次触发某些命令时创建多个SAGA,这些命令最终由多个聚合处理 发送第二个命令(cmd2),该命令还将导致各种命令/事件/命令序列 以示意图形式: cmd0 -> AR0 -> evt0 -> evtHandler -> cm

我正在维护一个源于事件的应用程序,恐怕它已经偏离了正轨

在一种情况下,聚合根收到一个命令,该命令发布一个事件,该事件由一个事件处理程序处理,该事件处理程序需要做两件事:

  • 将命令(cmd1)发送到另一个聚合根目录,该聚合根目录将发布一个事件,该事件将在每次触发某些命令时创建多个SAGA,这些命令最终由多个聚合处理
  • 发送第二个命令(cmd2),该命令还将导致各种命令/事件/命令序列
  • 以示意图形式:

    cmd0 -> AR0 -> evt0 -> evtHandler -> cmd1 -> AR1 -> evt1 -> saga stuff and more cmds and evts
                                     |-> cmd2 -> AR2 -> evt2 -> more saga stuff, cmds and evts
    
    所有事情都发生在同一个线程中,所有事情都发生在第一次处理命令时启动的一个事务中

    现在,目标是:所有源自第一个命令(cmd1)的事件、saga和聚合调用应首先发生,然后所有源自第二个命令(cmd2)的事件、saga和聚合调用应首先发生

    下面是观察结果:cmd1调用发布evt1的AR1,但之后cmd2调用发布evt2的AR2。来自cmd1的所有其他事件和命令都与来自cmd2的事件和命令混合在一起

    首先,我认为我可以使用
    UnitOfWork
    解决这个问题,但即使显式地创建一个单独的工作单元来处理cmd1,也不能解决这个问题。查看
    AbstractEventBus
    中的实现,我发现事件只是合并到父工作单元中,因此最终与源自cmd2的事件合并


    这里有一个问题:有没有一种方法可以在调用cmd2之前先调用cmd1并等待处理该命令产生的所有效果,同时仍然保留我当前拥有的事务原子性?

    老实说,如果应用程序中的组件不太依赖该顺序,则最好是这样。 这本质上意味着您有不同的消息处理组件,本质上可能是不同的微服务,但它们都是绑定在一起的,因为顺序很重要

    理想情况下,您应该将组件设置为独立工作。 因此,聚合处理一个命令并发布结果,完成。 传奇故事对事件做出反应,不管事件来自何处,并通过行动(如命令调度)对事件做出反应

    在这里,接受可能发生的情况会有所帮助,因为它将放弃等待一个过程完成的全部要求

    从理论上讲,这将是我的回应

    从一个更务实的角度来看你的问题,我想指出这听起来像是你要进入的兔子洞。您不仅希望执行
    cmd1
    处理,还希望解决所有传奇中的事件处理,包括由此产生的命令,对吗?谁来告诉我传说的数量?或者这些saga调度需要考虑的命令数量是多少?随着时间的推移,这些标准可能会发生变化,增加了“在单个事务中”需要发生的更多事情

    嗯,是的,有一种方法可以等待来自某些部分的处理,将它们全部拉入一个事务中。但老实说,我不建议你走这条路,因为这只会让使用这种基于消息的系统变得越来越复杂

    关键是所有的影响都是什么。从发送该命令的角度来看,您应该只关心该确切的命令是否成功地处理了yes或no,这就是问题应该结束的地方

    我知道这并不能为您提供一个简单的编程解决方案,因为您需要调整设计。但我认为脱钩是唯一正确的方法

    这是我的两分钱的情况,希望这有助于你进一步在任何方式一月


    消息预期解释更新 本质上,在Axon应用程序中使用的消息形成了一个边界。一个边界,在此边界之后,组件基本上不知道要处理这些消息的内容。每条消息的行为稍有不同,但可能也会澄清您打开的是什么:

    • 命令-命令始终路由到单个实例上的单个句柄。此外,您可以预期一个响应,以OK或NOK的形式。OK表示处理程序是
      void
      或已创建实体的标识符(如聚合本身)。NOK通常是您从命令处理方法中抛出的异常,这表明出现了错误或命令无法执行,应该让调度端知道
    • 事件-事件将广播到订阅了
      EventBus
      的任何组件,以处理给定事件。请注意,事件处理在时间上与事件的实际发布点分离。这意味着事件处理的结果不可能(或应该)返回给事件的调度程序
    • 查询-查询消息可以以多种形式发送。单个组件最适合回答查询(称为点对点查询)。您还可以将查询分派给多个处理程序并聚合结果(称为分散-聚集查询)。最后,您可以通过执行“订阅查询”来订阅查询模型,该查询本质上是一个点对点的组合,然后是一个
      流量
      更新。显然,查询分派意味着您正在从某个组件接收结果。只是你可以自由地进行查询。如果需要任何关于“最新”的保证,则查询响应的准确性应该是所发送查询的实现的一部分,以及
      @QueryHandler
      注释方法如何处理查询
    希望这能为Axon applic中每条消息的作用提供一些额外的清晰性