我正在开发小型CQRS + ES框架并使用它开发应用程序。在我的系统中,我应该记录客户端的一些操作并将其用于分析,统计,并且可能在将来使用它在域中执行某些操作。例如,客户端(在网络上)下载一些资源,我需要保存日期,时间,类型(下载,部分,...),来自地区或国家(可能是IP)等,然后在某些视图客户端可以看到下载次数或一些复杂的报告。我不确定如何实现这一点。
第一个解决方案创建分析上下文和一些聚合,在每个客户端操作中发送一些命令,如IncreaseDownloadCounter(resourced)
他们处理命令并引发域事件和更新视图,但在这种情况下,首先发生下载那个,我发送命令所以这不是真正的命令,而在另一方面版本冲突增加。
第二个解决方案是从客户端引发事件并基于它更新视图模型,但在这种类型的处理中,我的事件不存储在事件存储中,因为它不是通过命令引发的,并且永远不会更改任何域上下文。如果将它存储在事件存储中,则在获取其他用途之后没有聚合来处理它。
第三种解决方案是提升事件,从客户端和我将其存储在其他数据库上可能对于每种类型的事件都有特殊的表,但是以这种方式处理事件句柄我有多个事件存储具有不同的模式并且很难重新创建视图模型和跟踪事件用于重新创建上下文状态,以便将来如果我添加一些域以供使用此类事件,那么它很难使用事件。
此方案的最佳方法和解决方案是什么?
答案 0 :(得分:0)
第一个解决方案创建分析上下文和一些聚合
毫无疑问是错误的答案;事件已经发生,因此域模型抱怨为时已晚。
你所拥有的是一系列事件。将它们放在用于聚合事件流的同一事件存储中是可以的。把它们放在一个单独的商店也没关系。所以你需要一些其他约束才能做出好的选择。
通常,读取的数量远远超过写入数量,因此可能会出现这些事件会使域存储资源饱和的问题。这可能会促使您将这些事件与数据模型分开存储(现有技术:我们通常将业务数据保存在我们的持久记录簿中,但服务器接收的http请求序列通常会写入日志... )
如果您支持操作视图,请按重新启动后恢复状态的要求。您可以通过构建事件计数的内存模型来构建视图,并使用更实用的事件来表示事件。
感谢您的完整答案,所以我应该创建类似ES模式的东西,没有一些字段(聚合名称或类型,版本等),并在该存储库中收集客户端事件,一些脱机过程读取和更新读取模型或创建命令在域空间上做某事。
是这样的,是的。如果客户端的视图实际上根本不需要模型的任何验证,那么从外部提供的事件构建读取模型就可以了。
您是否建议保存用户和发件人应用的某些声明或授权令牌,以便在其他进程中进行验证?
也许,也许不是。令牌描述了事件的权限;我们自己的事件处理程序是从事件派生的命令的权限。这是一个有趣的问题,可能需要更多的背景 - 我建议你在这一点上提出一个新的问题。