Как я могу с помощью Axon повторно инициализировать некоторое значение с той же первой командой InitAvailableQuantityCommand?

Предположим, у нас есть запас. этот запас должен сохранять идентификатор продукта и доступное количество. пользователь этого запаса может часто обновлять (InitAvailableQuantityCommand) доступное количество. если какой-то продукт был продан, наша система получит событие soldEvent (DecreaseAvailableQuantityCommand), и доступное количество проданного продукта должно быть уменьшено.

он хорошо работает с приведенным ниже агрегатом, пока, если я снова не попытаюсь повторно инициализировать запас с помощью InitAvailableQuantityCommand, событие будет проигнорировано и возникнет ошибка

Событие для агрегата [3333] в последовательности [0] уже было вставлено"

То, что я пытаюсь достичь, следующее:

  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), и в этот момент она не работает и не работает.

Что я не так?

спасибо.

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

person user1167253    schedule 24.10.2018    source источник


Ответы (2)


InitAvailableQuantityCommand создает агрегат. Агрегаты по своей сути обладают идентичностью. Таким образом, Совокупный идентификатор предназначен для обозначения того, кто/что это такое. Когда вы используете источник событий, что вы делаете в Axon по умолчанию, Магазин событий гарантирует, что вы не будете добавлять события с одинаковым совокупным идентификатором и порядковым номером. Однако когда вы публикуете InitAvailableQuantityCommand во второй раз, вы указываете платформе опубликовать событие с тем же совокупным идентификатором и порядковым номером.

Следовательно, ваше решение для моделирования должно быть немного другим. Действие (также известное как команда) создания экземпляра агрегата отличается от его сброса. Таким образом, я бы предложил добавить другую команду для сброса вашего агрегата до его начальных значений.

person Steven    schedule 25.10.2018

Судя по вашему фрагменту кода, InitAvailableQuantityCommand обрабатывается конструктором. Это означает, что Axon предполагает создать новый экземпляр агрегата. Но поскольку вы ожидаете загрузки экземпляра, происходит столкновение идентификаторов (к счастью). Что вам нужно сделать, так это создать другую команду, которая содержит ту же информацию, но обрабатывается методом экземпляра. Это может быть то, что вы хотите сделать в любом случае, потому что существует концептуальная/функциональная разница между инициализацией в первый раз и «сбросом».

В будущих версиях Axon мы будем поддерживать функцию типа «создать или обновить», когда одна команда может выполнять обе роли.

person Allard    schedule 25.10.2018