Domain driven design 从事件处理程序内部加载事件?

Domain driven design 从事件处理程序内部加载事件?,domain-driven-design,cqrs,event-sourcing,ddd-repositories,eventstoredb,Domain Driven Design,Cqrs,Event Sourcing,Ddd Repositories,Eventstoredb,我们有一个使用GetEventStore的事件源系统,其中命令端和反规范化程序在两个单独的进程中运行 我有一个事件处理程序,它可以在用户保存应用程序时发送电子邮件(ApplicationSaved事件),我需要对此进行更改,以便对给定的应用程序只发送一次电子邮件 我可以看到一些这样做的方法,但我不确定哪种方法是正确的 1) 我可以查看read store,看看是否有匹配的应用程序,但是不能保证在我的电子邮件处理程序处理事件时数据会在那里 2) 我可以将一些内容附加到我的ApplicationSa

我们有一个使用GetEventStore的事件源系统,其中命令端和反规范化程序在两个单独的进程中运行

我有一个事件处理程序,它可以在用户保存应用程序时发送电子邮件(ApplicationSaved事件),我需要对此进行更改,以便对给定的应用程序只发送一次电子邮件

我可以看到一些这样做的方法,但我不确定哪种方法是正确的

1) 我可以查看read store,看看是否有匹配的应用程序,但是不能保证在我的电子邮件处理程序处理事件时数据会在那里

2) 我可以将一些内容附加到我的ApplicationSaved事件,可能是
修订版
,它在每次后续保存时都会递增。然后,我只在
Revision
为1时发送电子邮件

3) 在我的事件处理程序中,我可以使用存储库从我的事件存储中为匹配的客户加载事件,并在某种程度上构建一个独立于我域中的聚合。它可以包含一个我可以用来做决定的应用程序列表

我的想法:

1) 这似乎是不可能的,因为数据可能在读存储器中,也可能不在读存储器中

2) 如果数据可以从事件流中派生,那么它不需要位于事件本身

3) 我倾向于这一点,但这意味着在读写双方之间有一个清晰的分离,这似乎是违反了这一点。这是允许的吗

我可以看到一些这样做的方法,但我不确定哪种方法是正确的

没有完美的答案——在大多数情况下,外部可观察到的副作用独立于你的记录;在发送电子邮件但系统不知道的情况下,或者在系统记录发送电子邮件但实际发生故障的情况下,您总是可能会遇到某些故障模式

一个很好的答案是:你通常会从一个发送电子邮件的工具开始,并作为一个事件报告电子邮件是否成功发送。这基本上是一个事件流——你的模型不能否决邮件是否被发送

有了这一部分,您就可以有效地运行一个查询,询问“我现在需要发送哪些电子邮件?”您可以将
应用程序保存的事件与
EmailSent
事件折叠起来,从中计算需要做的新工作

Rinat Abdullin在文章中建议使用人工操作员来驱动流程。想象一下,建立一个屏幕,显示需要发送的电子邮件,然后有按钮,人们说要实际执行“它”,当人们点击按钮时,发送电子邮件的工作就会发生

人类所看到的是一个视图或投影,也就是说,从记录的事件计算出的系统状态的读取模型。按钮单击将向“写入模型”发送消息(按钮单击事件通知系统尝试发送电子邮件并记录结果)

当您需要采取行动的所有信息都包含在您要对之作出反应的事件的表示中时,通常会考虑将数据“推送”给订阅者。但当订户需要有关先前状态的信息时,基于“拉”的方法通常更容易推理。交付的事件向项目发出唤醒信号(减少延迟)


Greg Young在他的演讲中详细介绍了推送和拉送。你想出了什么解决方案?我的第一个想法是定制投影本可以帮助你。但实际上,如果您遵循CQR/E,那么您将拥有ReadModel和企业服务总线。在更新ReadModel和阅读ES之间,应该有其他决定是否发送电子邮件的因素。您可能不应该将EventStore用作事件发射器。。它只存储事件。您需要根据业务规则做出其他决定。也许是传说?可能只是域外的其他持久订户