CQRS+ES:客户端日志作为事件

CQRS+ES: Client log as event

我正在开发小型 CQRS+ES 框架并使用它开发应用程序。在我的系统中,我应该记录客户端的一些操作并将其用于分析、统计,并可能在未来用它做一些领域内的事情。例如,客户端(在网络上)下载一些资源,我需要保存日期、时间、类型(下载、部分……)、来自地区或国家(可能是 IP)等,之后在某些视图客户端中可以看到下载计数或一些复杂的报告。我不确定如何实现这个羽毛。

第一个解决方案创建分析上下文和一些聚合,在每个客户端操作中发送一些命令,如 IncreaseDownloadCounter(resourced) 它们处理命令并引发域事件和更新视图,但在这种情况下首先发生下载,然后,我发送命令,所以这不是真正的命令,另一方面版本冲突增加。

第二种解决方案是从客户端引发事件并更新基于它的视图模型,但在这种类型的处理中,我的事件不会存储在事件存储中,因为它不是通过命令引发的,也不会更改任何域上下文。如果将它存储在事件存储中,则在提取后没有聚合来处理它以用于其他用途。

第三种解决方案是从客户端引发事件,我将其存储在其他数据库中,可能每种类型的事件都有特殊的 table,但在这种事件处理方式中,我有多个不同的事件存储schema 并且很难重新创建视图模型和跟踪事件以重新创建上下文状态,因此将来如果我添加一些域来使用此类事件,则很难使用事件。

这种情况的最佳方法和解决方案是什么?

First solution creates analytic context and some aggregate

毫无疑问是错误的答案;事件已经发生,领域模型抱怨已经来不及了。

您拥有的是事件流。将它们放在您用于聚合事件流的同一事件存储中就可以了。将它们放在单独的商店中也可以。所以你将需要一些其他约束来做出好的选择。

通常情况下,读取的数量远远超过写入的数量,因此可能会担心这些事件会使域存储饱和。这可能会促使您将这些事件与您的数据模型分开存储(现有技术:我们通常将业务数据保存在我们的持久记录簿中,但服务器接收到的 http 请求序列通常被写入日志...... )

如果你是支持操作视图,就强推要求重启后恢复状态。您可能能够通过事件计数的内存模型构建您的视图,并使用更实用的东西来表示事件。

Thanks for your complete answer, so I should create something like the ES schema without some field (aggregate name or type, version, etc.) and collect client event in that repository, some offline process read and update read model or create command to do something on domain space.

类似的东西,是的。如果客户端的视图实际上根本不需要您的模型进行任何验证,那么从外部提供的事件构建读取模型就可以了。

Are you recommending save some claim or authorization token of the user and sender app for validation in another process?

也许,也许不是。令牌描述了事件的权限;我们自己的事件处理程序是 command(s) 的权限,is/are 从事件派生。这是一个有趣的问题,可能需要更多的上下文——我建议你就这一点提出一个新问题。