我已经开始计划我的第一个带有事件源的CQRS项目,并且由于时间限制,模型的一部分将保留在XML文件中。我从DDD中理解的是,每次更新都是对聚合根进行的,如果我想从第一个更改另一个聚合根(在域中引发一个事件),那么首先是修改第二个聚合的命令。每个变更都有自己的交易边界。
现在,我担心的是,如果我已将更改提交到第一个聚合(在数据库中),我该如何处理第二个聚合(在这种情况下写入文件)失败的情况?
我可以先发出一个命令来首先更新文件(第二个聚合),然后发出命令来更改第一个聚合但是再一次我可以让第二个命令失败但在这种情况下我们有两个单独的命令似乎违背在第一种情况下处理的域中提出的事件的想法。
我想即使我没有使用文件并且所有更改都记录在数据库中,第二次聚合更改也有可能失败。我是否认为这是正确的?
仍然试图让我的头脑中的概念清晰明了,所以任何帮助都会受到赞赏。
答案 0 :(得分:2)
第二个聚合可以发出类似UpdateFailed事件的内容。这反过来可以通过向第一个聚合发送回滚命令来处理。
你有一个具体的例子吗?通常,通过改进模型可以解决跨越聚合边界的事务的需要。
更新:还要看一个名为“Saga”的概念。一个传奇可以成为像你这样的交叉聚合流程的有用协调者。 saga基本上是一个事件处理程序,它根据收到的事件提交命令。一个saga可以只是一个无状态协调器,但它也可以是有状态的,因此它知道在后续的一个失败的情况下必须补偿哪些命令。只是google“CQRS Saga”并从那里开始。特别是Greg Young和Rinat Abdullin撰写的文章非常有用。
答案 1 :(得分:1)
我认为你在这里有更多关于事务一致性的问题。由于您没有为会话提供真正的业务背景,因此很难完全评论适当的解决方案。
但是,通常情况下,如果第二个聚合必须根据第一个聚合的命令进行更新,那么它们可能属于同一个事务(DDD'Bounded-Context')。没有上下文,真的很难知道。
否则,通常,如果第二个聚合已订阅第一个事件,则在事务中接收该消息(此时属于第二个聚合),如果无法满足该操作,则事件的处理是回滚并重新尝试(或推送到另一个地方进行手动操作(如错误队列))。
这有帮助吗?