如何使用Akka建模聚合关系

huangapple go评论65阅读模式
英文:

How to model aggregates relations with Akka

问题

我在演员模型中遇到了关系的问题。让我用一个简单的例子来说明。系统中有两种演员类型:仓库和物品。物品始终分配给特定的仓库。AddStock命令允许增加分配给给定仓库位置的库存数量。只有仓库知道自己的位置,因此物品必须询问其所属仓库是否可以执行自己的业务逻辑。我已经考虑了一些解决方案:

  1. 命令AddStock包含对仓库分片区域的ActorRef,允许物品向仓库询问位置。
  2. 以某种方式仅允许仓库发出AddStock命令,从而允许预验证位置。不确定如何实现这一点,我考虑过私有命令或某些识别过程。

我都不喜欢这些解决方案。它们为简单的任务增加了许多不必要的复杂性。我认为这可能是面向对象思维的问题,分布式演员世界受其自身规则管理。

在我的情况下,我将物品和仓库都视为单独的聚合。它们都以持久性演员(带有群集分片)的形式实现。

只要您假设只有仓库可以调用Item::AddStock,一切都很简单。然后,仓库只需在调用之前验证位置。但是有人可能直接调用Item并跳过所有验证。物品无法知道是否是正确的仓库发出了调用。在纯面向对象/领域驱动设计方法中,可以轻松实现。物品知道仓库ID,并且更改数量的过程如下所示:

item.addStock("L2", 100, warehouse)

知道仓库ID的物品可以验证提供的仓库是否是正确的仓库。而拥有仓库的物品可以询问位置是否有效。我当前的物品处理程序实现:

case AddStock(region, location, quantity) => {
  region ? EntityEnvelope(warehouseId, HasLocation(location)) map (
    _ => VerifiedAddStock(quantity)
  ) pipeTo self

VerifiedAddStock是物品的私有对象,所以我知道谁是命令的发出者(几乎是因为它不能强制执行身份)。

因此,问题是如何在演员世界中建模这种关系?在传递分片区域引用之间传递是一种常态吗?

有人可能会建议,由于不正确的聚合/演员边界,这本身就是设计缺陷,但这只是一个例子。

英文:

I struggle with relations in actor model. Let me use simple example. There are two actor types in the system: Warehouse and Item. Item is always assigned to particular Warehouse. AddStock command allows to increase stock quantity assigned to given warehouse location. Only warehouse knows own locations so Item must ask its Warehouse if the location is valid to perform own business logic. I've thought of some solutions

  1. Command AddStock contains ActorRef to warehouse shard region which allows Item to ask the Warehouse about location.
  2. Allow somehow only the Warehouse to issue command AddStock which allows to prevalidate locations. Not sure how to achieve this, I've thought about private commands or some identification process

I do not like neither solutions. It adds lot of unnecessary complexity to simple task. I think it may be issue with OOP thinking here and distributed actors world is governed by its own rules.

In my scenario I perceive both Item and Warehouse as separate aggregates. They are both implemented as Persistent Actor (with Cluster Sharding).

All is easy as long as you assume that only Warehouse may call Item::AddStock. Then Warehouse just validates the location before the call. But one may call Item directly and skip all that validation. Item has no way to know if the proper warehouse made the call. It is easy to achieve in pure OOP/DDD approach. Item is aware of warehouse ID and changing quantity would look like this

item.addStock("L2", 100, warehouse)

Item knowing warehouse id may validate if provided warehouse is the warehouse. And having warehouse may ask if location is valid. My current implementation of Item handler:

case AddStock(region, location, quantity) => {
  region ? EntityEnvelope(warehouseId, HasLocation(location)) map (
    _ => VerifiedAddStock(quantity)
  ) pipeTo self

VerifiedAddStock is Item`s private object so I am sure who is the command issuer (almost because it not enforce identity).

So the problem is how to model such relation in Actor world? It is the norm to pass around shard region ref?

One may suggest that it is design flaw itself due to improper aggregate/actor boundaries but this is just an example.

答案1

得分: 2

以下是翻译好的内容:

如果答案是否定的,那么我会将Item视为关联仓库位置的子项(即颠倒关系的方向)。只要仓库永远不会为Item提供ActorRef,您可以确保只有它可以向Item actor发送消息(Akka Typed允许您做出这种静态保证)。

如果答案是肯定的,我建议在仓库库存的背景下,一个Item包含的恰好是该背景中所需的信息,例如,类似于目录描述的内容是不同背景(很可能是不同的服务)的责任,如果目录描述背景需要了解有关库存的某些信息(例如,它是否随时可用),那么它应该利用仓库库存发出的领域事件。

英文:

Does Item have any information (e.g. description) which Warehouse isn't going to care about?

If the answer is no, then I would just treat Item as a child of the associated warehouse location (i.e. invert the direction of the relation). As long as the warehouse never gives out an ActorRef for the Item, you can be sure that only it can send messages to the Item actor (Akka Typed lets you make this static guarantee).

If the answer is yes, I'd suggest that in the context of warehouse inventory, an Item consists of exactly the information needed in that context and, for instance, something like catalog descriptions is the responsibility of a different context (very likely a different service) and if there's something the catalog description context needs to know about inventory (e.g. whether it's in-stock anywhere or not), then it should leverage domain events emitted by the warehouse inventory.

huangapple
  • 本文由 发表于 2020年9月11日 16:30:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63843508.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定