NEventStore:5.1
简单设置:WebApp(Asp.NET 4.5)==命令端
我正在寻找不丢失命令的"正确"方法,关注sagas/流程管理器,它们可能会无休止地等待从未处理过的命令产生的事件。
旧:Dispatchers
我最初使用sync命令,但着眼于sagas/流程管理器,我认为首先存储它们,然后通过SyncDispatcher(或AsyncDispatcher)获取它们会更安全。否则,我担心的是,如果一个传奇试图发送一个命令,但由于应用程序崩溃/poweloss/导致命令没有完成,它就会丢失,没有人会知道。
因此,我创建了一个命令流,并将每个命令附加到其中。如果该命令已被处理,则会显示IsDispatched
奏效了。
轮询客户端和命令流
现在调度员已经过时了,我切换到PollingClient
。我丢失的是Dispatched
信息。
出现启动问题:
我天真地开始从当前最新的检查点轮询,但当应用程序重新启动时,有可能在崩溃前存储了命令,但没有执行,因此丢失了(实际上发生了这种情况)。
我刚刚遇到了的想法:
将命令的基本结果存储为另一个流中的(非域)事件
该流将包含CommandSucceeded
和CommandFailed
事件
每当应用程序启动时,提取最新的命令id或命令检查点编号,用于在该编号之后加载命令。。。
问题
- 我担心同步命令处理会导致丢失传奇生成的命令的危险,这是错误的吗?如果是,为什么
- 这通常是一个好主意吗:一个大的命令流
- 这通常是一个好主意吗:将通用命令结果事件存储在流中
您可以:
- 将您的命令存储在命令队列|持久日志中
- 使用命令id(guid)作为NEventStore上的提交id
- 将命令标记为在命令处理程序|管道挂钩|轮询客户端中执行
NEventStore在相同的AggregateId(streamid)+CommitId上为您提供了幂等性,因此,如果您的应用程序在命令被标记为已处理并重播命令之前崩溃,则生成的提交将被NES自动丢弃。
Afaik NEventStore旨在作为事件源的存储,即将域对象存储为事件流。命令和传奇与此无关。它是您的服务总线,应该负责耐用性和传奇管理。
就我个人而言,我将事件存储简单地视为存储库细节。应用程序服务(命令处理程序)将在生成的事件持久化后对其进行调度。
如果应用程序崩溃,并且服务总线是耐用的(而不是内存总线),那么事件/命令将再次自动处理,因为服务总线应该检测消息是否未成功处理。当然,由于这个原因,您的消息处理程序应该是幂等的。