如何跨聚合根处理并发约束

Den*_*men 6 domain-driven-design eventual-consistency aggregateroot

我担心我已经知道了答案,但我希望有人可以提供以前没有找到的替代解决方案.一如既往地根据有效聚合设计做DDD 比我想象的要困难,但这是我的情景.

  • 我们有两个AR,User和RoleGroup
  • 可以向用户授予特定的RoleGroup,从而获得该角色组中的角色(集合值对象)提供的权限.角色组的身份在用户AR中保留为另一个VA.
  • 从系统中删除RoleGroup时,我们引发一个域事件,处理程序使用该事件来查找引用该RoleGroup的所有用户并删除该引用.相应的投影非规范化器将使用相同的事件来更新用户的有效角色.这是授予该用户的各个角色和所有已授予的RoleGroup的角色的组合.
  • 这不一定是事务性的(现在它可以最终一致).
  • 我们使用Jonathan Oliver的EventStore 3.0以及来自Lokad.CQRS和NCQRS的元素来使用事件采购.

因此,理论上,当一个请求(它是一个ASP.NET MVC应用程序)正在执行上面提到的场景时,另一个请求可能会向用户授予相同的RoleGroup.如果在上述域事件处理程序扫描与该RoleGroup相关的用户之后发生这种情况,则该请求将完成.此时,您有一个已删除的RoleGroup(尽管不是物理上的)和仍保留该RoleGroup标识的User.

你怎么防止这种情况?我们目前正在考虑使用户的身份被授予该RoleGroup AR的特定RoleGroup部分,因此删除RoleGroup并将其授予用户将导致乐观的并发冲突.但不知何故,这不是正确的解决方案.

Yve*_*out 1

这类似于解决唯一性约束的方式。

假设有一个具有 SERIAL 行为的角色组和用户的投影。当角色组被存档(即它们不能再使用)时,位于投影顶部的反应位可以通知所有已被授予所述角色组的用户他们不再是该角色组的一部分。当同时将此存档角色组授予一个用户(或一组用户)时,可以利用投影的串行性质来告诉该用户他们不再是该组的一部分。

话虽如此,这只是家政服务。只有当角色组和用户习惯后,正确的视图才变得重要。由于我认为角色组将带有 IsArchived 位,因此我可以在那时安全地过滤掉它们,而不必担心一些悬而未决的边缘情况,我们仍然需要证明它必须以自动方式解决。

顺便说一句,扫描事件日志也会揭示这种情况,即是否有任何用户被授予在该时间点之前(或在该时间点附近)存档的角色组?管理员可以通过向用户聚合发出补偿命令来解决此问题。

“这要看情况”TM

编辑:我已经给出了这个问题的技术解决方案。我鼓励其他读者探索建模和解决此类问题的不同方法。有时,甚至在大多数时候,答案根本不是技术性的。YMMV。