我如何使用Axon使用相同的第一个InitAvailableQuantityCommand重新初始化某些值?

时间:2018-10-24 16:31:19

标签: domain-driven-design event-sourcing axon

假设我们有库存。该库存应保留产品编号和可用数量。该库存的用户可以经常更新(InitAvailableQuantityCommand)可用数量。 如果已售出某些产品,我们的系统将获得一个soldEvent(DecreaseAvailableQuantityCommand),并且已售产品的可用数量应减少。

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

  

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

我尝试达到的目标是:

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

我怎么了?

thx。

@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();
}
}

2 个答案:

答案 0 :(得分:1)

InitAvailableQuantityCommand实例化一个聚合。聚集体固有地具有标识。这样,就可以使用“聚合标识符”来表示它是谁/什么。当您进行事件来源时(默认情况下在Axon中使用事件源),事件存储将确保您不会添加具有相同聚合ID和序列号的事件。但是,当第二次发布InitAvailableQuantityCommand时,是在告诉框架发布具有相同聚合ID和序列号的事件。

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

答案 1 :(得分:1)

从您的代码段来看,>> *245# system will display 1 send money 2 balance Text BOX 由构造函数处理。这意味着Axon期望需要创建一个新的聚合实例。但是,正如您期望加载的实例一样,标识符会发生冲突(很幸运)。 您需要做的是创建一个包含相同信息但由实例方法处理的不同命令。无论如何,这可能都是您想要做的,因为在首次初始化和“重置”之间存在概念/功能上的差异。

在将来的Axon版本中,我们将支持“创建或更新”类型的功能,其中单个Command可以同时扮演这两个角色。