流和聚合的事件溯源组织

Event Sourcing organization of streams and Aggregates

在 ES 中组织事件流的最佳方式是什么。对于事件流,我的意思是将所有事件聚合在一起。

假设我有一个 project,其中包含一些数据和 tasks 的列表。

现在我有一个 Guid 作为 AggregateID 作为我的 streamID。 到目前为止我可以 -> 使用该 ID 为给定项目重新创建状态 -> 我可以 assemble 使用自定义投影

projects 列表

问题是如何处理todos? 这也应该在 project stream id 下面处理还是应该有自己的 todo stream id?

如果 todo 有它是单独的 stream 如何将它 link 给拥有者 projectproject 如何知道给定 project 的所有 todo streams。 这意味着对 todo list 的所有更改也应在项目中被识别为 CommandsEvents(更多事件)。

如果我也想允许 free todo's 与项目无关。它是否需要有自己的类型和 stream 来处理顶部的 freeTodo。所有 todos 的列表是否 project 相关与否将是所有 todofreeTodo 相关流的投影?

所以我想主要问题是如何处理嵌套聚合以及如何定义事件存储流和 linking?

我们将不胜感激任何提示、技巧、最佳实践或资源。

// 编辑更新

首先感谢@VoiceOfUnreason 花时间详细回答这个问题。我添加了标签 DDD,因为我有一种奇怪的感觉,它与限界上下文问题相关联,而限界上下文问题在大多数情况下都没有非黑即白的决定。显然领域有更多的深度和细节,我简化了例子。下面我分享了一些让我质疑的更多细节。

在我的第一个想法中,我为 todo 定义了一个聚合,并为 project id 定义了一个 属性。我将此 project 属性 定义为 option type (Nullable) 以涵盖项目相关和免费待办事项之间的区别。但是遵循用例/业务规则让我重新思考。

c) 提供某种服务,为项目验证提供 todo 信息,以某种方式引用 a.)。

而且感觉真的很结合=-/

如果您或其他人有时间在这里分享更多细节和意见,那就太好了。太感谢了。

提醒:中的战术模式主要是对 OO 最佳实践的列举。如果它在 OO 中是个坏主意,那么它在 DDD 中可能是个坏主意。

the main question is how do I handle nested aggregates

您重新设计了模型。

嵌套聚合表明您已经完全迷失了情节;聚合边界不应重叠。重叠边界类似于封装违规。

If a todo has it's separate stream how would one link it to the owning project.

最有可能的答案是 Todo 会有一个 projectId 属性,它的值通常指向系统中其他地方的项目。

How is the project aware of all the todo streams for a given project.

不是。您可以构建包含项目历史和待办事项历史的读取模型以生成单个只读结构,但项目聚合——负责确保边界内状态的完整性——不会无法查看待办事项对象的内部。

Meaning all changes to the todo list should be also recognized as Commands and Events (more Events) in the project.

不,如果它们是单独的集合,那么事件是完全分开的。

在某些情况下,您可能会将待办事项产生的事件中写入的值用作分派给项目的命令中的参数,反之亦然,但您需要将它们视为具有对话的独立事物可能会,也可能不会达成协议。

可能性:独立的待办事项可能与与项目关联的待办事项确实不同。请咨询您的领域专家——他们可能在通用语言中有单独的术语,或者在讨论细节时您可能会发现他们应该在 UL 中有不同的术语。

或者,待办事项可以是单独的聚合,业务适应有时项目状态和待办事项状态不一致的事实。您可以检测差异并根据需要缓解问题,而不是试图阻止模型进入聚合不一致的状态。