我目前每个聚合根和两个聚合根Room
和RoomType
都有一个事件流。
Room
的行为取决于RoomType
是什么。为了将两个聚合分开,RoomType
仅在Room
聚合中表示为roomTypeId。 RoomType
的更改由RoomTypeChanged
事件表示。
RoomTypes
可以单独管理,并且需要在不同的聚合中。
现在考虑以下用例:
当用户使RoomType
无效时,拥有该Rooms
的所有Roomtype
都应切换为后备RoomType
。
我想过几种方法,但所有这些方法似乎都有问题:
让事件监听器监听RoomTypeInvalidated
- 事件,并在所有SwitchToFallbackRoomType
上发送Room
- 具有Roomtype
的聚合。
我怎么会这样做?除非我访问我的readmodel,这似乎是不正确的,否则无法知道哪些聚合具有Roomtype
。
即使我要加载所有聚合,也无法仅加载该类型的聚合,因为我无法加载所有流的子集(使用geteventstore)。
将RoomTypeChanged
- 事件重新应用于Room
聚合时,不要只应用它,请检查RoomType
是否仍然存在,但是,我怎么知道哪个RoomTypes
存在(我和1相同,但倒置了)?此外,在重新应用事件时加入逻辑似乎是错误的,它们应该代表我认为的状态变化。
你会如何解决这个问题?
答案 0 :(得分:0)
为什么不为每个房型使用流程管理器并将房间列表作为流程管理器的属性? 从服务或命令处理程序查询读取模型将无法保证一致的框架。如果房间被分配到无效的房间类型但读取的模型尚未更新,该怎么办? (这就是我所面临的情景)
答案 1 :(得分:0)
通过确保每次数据完全一致来解决此问题,这是对设计的影响。事件采购假设系统最终一致,因此在读取模型中出现不一致是正常的和预期的。
解决此问题的最佳方法是使用新的无效TypeId(您的解决方案1)查询所有房间的读取模型。在更新了所有这些房间之后,有可能有一些未更新的落后者,所以你稍后重新运行事件处理程序(让我们说一分钟)。
此时(假设您的命令在创建房间时检查房间类型的有效性),不可能使用旧房间类型创建新房间,并且漫游者的读取模型应该已经稳定。因此,重新运行代码将更新剩余的所有内容。
答案 2 :(得分:0)
我们正在处理同样的问题,还有房间和房间类型。您遇到问题的解决方案可能来自关系,这是一个非问题。认为在一个非常数据驱动的领域开始思考行为是困难和困惑的。 我认为要解决问题,你必须挑战建议的解决方案。
在重新思考时,我们最终得到了像RoomAssignment和RoomAllocationSchedule这样的聚合,并发现RoomType主要用于将房间功能与外部频道/ OTA进行通信。
对我们需要的行为进行建模确实有帮助(因为一致性bounderies开始有意义),而不是建模数据并尝试在其上强制执行关系一致行为......
当我们确实需要跨聚合的一致性时,我们建模一个流程管理器/传奇,它本身是事务一致的,并向聚合发送消息。因此,我们有一个“RoomAssignmentDirector”汇总,确保在分配给房间等之前为房间分配房间。
希望它有所帮助。