问题描述
我在演员模型中为关系挣扎。让我举一个简单的例子。系统中有两种参与者类型:仓库和物料。物料始终分配给特定的仓库。 AddStock命令允许增加分配给给定仓库位置的库存数量。只有仓库知道自己的位置,因此Item必须询问其仓库该位置是否有效以执行自己的业务逻辑。我想到了一些解决方案
- AddStock命令包含对仓库分片区域的ActorRef,它允许Item向仓库询问位置。
- 仅以某种方式允许仓库发出命令AddStock,该命令允许预先验证位置。不确定如何实现,我已经考虑过私人命令或一些识别过程
我都不喜欢这两种解决方案。它为简单任务增加了很多不必要的复杂性。我认为这可能与OOP的思想有关,而分布式参与者世界受其自己的规则支配。
在我的场景中,我将物料和仓库视为独立的集合。它们都被实现为持久角色(具有群集分片)。
只要您假设只有Warehouse可以调用Item :: AddStock,这一切都很容易。然后,Warehouse仅在调用之前验证位置。但是可以直接调用Item并跳过所有验证。物品无法知道是否由适当的仓库打了电话。纯OOP / DDD方法很容易实现。项目知道仓库编号,更改数量看起来像这样
item.addStock("L2",100,warehouse)
知道仓库ID的项目可能会验证所提供的仓库是否是仓库。并且拥有仓库可能会询问位置是否有效。我当前对Item handler的实现:
case AddStock(region,location,quantity) => {
region ? EntityEnvelope(warehouseId,HasLocation(location)) map (
_ => VerifiedAddStock(quantity)
) pipeto self
VerifiedAddStock是Item的私有对象,因此我可以确定谁是命令发布者(几乎是因为它不强制执行身份验证)。
所以问题是如何在Actor世界中建立这种关系的模型?绕过碎片区域参考是正常的吗?
有人可能认为这是由于不正确的聚集体/角色边界导致的设计缺陷本身,但这只是一个例子。
解决方法
商品是否有仓库不关心的任何信息(例如说明)?
如果答案为否,那么我将把Item视为关联仓库位置的子项(即,反转关系的方向)。只要仓库从不为商品提供ActorRef,您就可以确保只有它可以将消息发送给Item参与者(Akka Typed可以使您获得此静态保证)。
如果答案是肯定的,那么我建议在仓库库存的上下文中,一个项目完全由该上下文中所需的信息组成,例如,目录描述之类的内容是另一个上下文的责任(非常可能是一项不同的服务),并且如果目录描述上下文需要了解有关库存的某些信息(例如,是否在任何地方都有库存),那么它应该利用仓库库存发出的域事件。