Domain driven design DomainEventPublisher一致性

Domain driven design DomainEventPublisher一致性,domain-driven-design,aggregateroot,Domain Driven Design,Aggregateroot,刚刚读过沃恩·弗农的书,我想知道与事件发布相关的失败 在第9页(PDF第3页)的给定示例中,我们调用DomainEventPublisher.publish()。正在发布的事件允许其他聚合执行其行为 我想知道的是:如果DomainEventPublisher.publish()失败会发生什么?如果DomainEventPublisher.publish()成功,但事务失败,会发生什么情况 实现如何处理这两种情况 如果DomainEventPublisher.publish()成功,但 交易失败

刚刚读过沃恩·弗农的书,我想知道与事件发布相关的失败

在第9页(PDF第3页)的给定示例中,我们调用
DomainEventPublisher.publish()
。正在发布的事件允许其他聚合执行其行为

我想知道的是:如果
DomainEventPublisher.publish()
失败会发生什么?如果
DomainEventPublisher.publish()
成功,但事务失败,会发生什么情况

实现如何处理这两种情况

如果DomainEventPublisher.publish()成功,但 交易失败

在这种情况下,我反对弗农方法。我更喜欢申请服务。这样,我可以使用事务(如果需要)持久化聚合执行的更改,如果一切正常,我将发布事件。这也有助于保持业务层完全干净和纯净

几句话,;如果事务失败,则不会引发任何事件

如果DomainEventPublisher.publish()失败怎么办

根据业务规则,域事件永远不会失败,因为它是已发生事件的通知。如果一个聚合对操作说是,并返回一个表示业务变化的事件;那么,世界上没有任何东西可以说这一行动不能进行或必须撤销

如果基础架构导致事件失败,那么您需要有工具在中断修复后(自动或手动)重新引发事件,并最终在系统中归档一致性。看一看。它提供重试、错误队列、日志等,以避免丢失事件。
如果消息系统已关闭,您至少可以使用事件日志将其重新放入消息系统。

DomainEventPublisher.publish()
是同步的。您需要设置一个将事件存储在与业务流程相同的数据库事务中的方法,这意味着您的事件存储必须能够与存储聚合状态所依赖的任何其他存储机制进行事务处理

一旦事件写入磁盘事务处理中,您就可以将它们放在消息队列中进行异步传递

还有其他已知的方法吗


嗯,您可以在AR上记录集合中的事件,而不是使用静态的
DomainEventPublisher
,就像在事件源中一样,然后实施集中机制来存储它们(例如事务挂钩、使用方面等)。

谢谢。我认为我的问题对于可能失败的事情还不够清楚:首先,我们可能无法触发事件(例如,消息传递系统暂时关闭)。第二件事是,在发布事件之后,正在进行的事务可能无法提交;因此,我们发布了一个事件,但自从事务失败后,事情并没有真正发生。但我要回答这两件事。我的回答中有什么让你觉得我误解了你的问题?我说的是发布事件,而不是处理它们:)我的回答是,更改Vernon策略允许你在事务提交时发布事件,或者在事务失败时不发布事件。
“我可以使用transacion(如果需要)持久化聚合执行的更改,如果一切正常,我将发布事件“
这毫无意义,给定的事件和ARs状态必须以原子方式存储。你刚才描述的方式将允许一个非常不一致的系统。如果事务提交,但发布事件失败怎么办?谢谢。我喜欢这个解决方案。还有其他已知的方法吗?这个例子在现实世界中不是很有弹性/可用。最可靠的模式是来自事件源的模式,事件根本没有发布,而是从事件存储中提取,事件消费者(readmodel或saga)跟踪处理的事件是否使用事务;它使聚合依赖于基础结构(这可以通过返回事件来减轻)@ConstantinGalbenu无论您是返回它们还是使用静态线程绑定的同步
DomainEventPublisher
都可以获得相同的精确结果和相同的可测试性。该模式确实使用数据库事务,但域无论如何都不知道这些事务。我真的不明白你的意思。@plalx聚合生成一个
IO
调用,我不喜欢这样。我保持聚合的纯粹性,没有副作用,事实上不依赖于基础设施或任何其他组件。@ConstantingAlbernu好吧,如果没有注册的处理程序执行IO,它们就不会进行IO调用,这意味着一切都可以在没有任何IO的情况下进行单元测试。ARs本身不依赖于基础设施组件或任何其他包。