0

假设我们有股票。此库存应保留产品 ID 和可用数量。该库存的用户可以频繁更新(InitAvailableQuantityCommand)可用数量。如果某些产品已售出,我们的系统将收到已售出事件(DecreaseAvailableQuantityCommand),并且已售出产品的可用数量应该减少。

它适用于下面的聚合,直到一件事,如果我再次尝试使用 InitAvailableQuantityCommand 重新初始化库存,该事件将被忽略并引发错误

已插入序列 [0] 处的聚合 [3333] 事件”

我试图达到的目标如下:

  1. InitAvailableQuantityCommand (productId = 1, 数量 = 10)
  2. DecreaseAvailableQuantityCommand(productId = 1,数量 = 1)
  3. DecreaseAvailableQuantityCommand(productId = 1,数量 = 1)
  4. 现在我们还有 8 种可用产品。
  5. 并且此时用户将使用 productId 1 的 20 个可用产品重新初始化库存。用户将发送一个新的 InitAvailableQuantityCommand (productId = 1, quantity = 20),此时它失败并且不起作用。

我错了什么?

谢谢。

@NoArgsConstructor
@Aggregate
@Data
public class AvailableQuantityAggregate {

private String partnerId;
private String productId;

@AggregateIdentifier
private String productVariationId;
private int quantity;

@CommandHandler
public AvailableQuantityAggregate(InitAvailableQuantityCommand cmd) {
    final ApplyMore apply = AggregateLifecycle.apply(AvailableQuantityInitializedEvent.builder()
                                                             .partnerId(cmd.getPartnerId())
                                                             .productId(cmd.getProductId())
                                                             .productVariationId(cmd.getProductVariationId())
                                                             .quantity(cmd.getQuantity())
                                                             .build());
}

@CommandHandler
public void handle(DecreaseAvailableQuantityCommand cmd) {
    AggregateLifecycle.apply(AvailableQuantityDecreasedEvent.builder()
                                     .productVariationId(cmd.getProductVariationId())
                                     .quantity(cmd.getQuantity())
                                     .build());
}

@EventSourcingHandler
protected void on(AvailableQuantityInitializedEvent event) {
    this.productVariationId = event.getProductVariationId();
    this.partnerId = event.getPartnerId();
    this.productId = event.getProductId();
    this.quantity = event.getQuantity();
}

@EventSourcingHandler
protected void on(AvailableQuantityDecreasedEvent event) {
    this.quantity = this.quantity-event.getQuantity();
}
}
4

2 回答 2

1

实例化InitAvailableQuantityCommand一个聚合。聚合本质上具有同一性。因此,聚合标识符用于表示它是谁/是什么。当您在 Axon 中默认使用事件源时,事件存储将确保您不会添加具有相同聚合 id 和序列号的事件。但是,当您InitAvailableQuantityCommand第二次发布时,您是在告诉框架发布具有相同聚合 id 和序列号的事件。

因此,您的建模解决方案应该有所不同。实例化聚合的操作(又名命令)与重置聚合不同。因此,我建议添加一个不同的命令来将您的聚合重置为其初始值。

于 2018-10-25T07:45:55.063 回答
1

从您的代码片段来看,InitAvailableQuantityCommand由构造函数处理。这意味着 Axon 预计需要创建一个聚合的新实例。但是正如您期望加载一个实例一样,标识符之间存在冲突(幸运的是)。您需要做的是创建一个包含相同信息但由实例方法处理的不同命令。无论如何,这可能是您想要做的,因为首次初始化和“重置”之间存在概念/功能不同。

在 Axon 的未来版本中,我们将支持“创建或更新”类型的功能,其中单个命令可以完成这两个角色。

于 2018-10-25T07:46:42.267 回答