распределенное использование aggregateidentifier - PullRequest
1 голос
/ 20 июня 2020

Мне было интересно, будет ли считаться плохой практикой использование совокупного идентификатора в сервисе в другом (расширенном) агрегате, который совместно использует то, что они оба вращаются вокруг одного и того же идентифицируемого объекта.

Проблема, с которой я столкнулся. в настоящее время мы хотим разделить некоторые logi c (ограниченный контекст, если хотите) на другую службу, которая изначально создавала агрегат.

В общем, это работает, как когда я отправить команду внутри второй службы, она будет обработана и обновлена. Поскольку я могу использовать EventSourcingHandler, чтобы также использовать события, созданные в другой службе, для управления ее состоянием, я получаю информацию о состоянии из источника, применяемого первым агрегатом служб.

Я волновался, что механизм снимков сработает против меня, но, видимо, он достаточно умен, чтобы хранить снимки отдельно, если я удостоверяюсь, что совокупное имя «типа» не то же самое.

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

Итак, я иду против того, как каркас аксонов предполагает использование агрегатов, или это жизнеспособный вариант использования?

@Aggregate
@Getter
@NoArgsConstructor
public class Foo {

  @AggregateIdentifier
  private String fooIdentifier;

  @CommandHandler
  public Foo(CreateFooCommand command) {
    apply(FooCreatedEvent.builder()
      .fooIdentifier(command.getFooIdentifier())
      .build());
  }

  @EventSourcingHandler
  public void on(FooCreatedEvent event) {
    this.fooIdentifier = event.getFooIdentifier();
  }

}


@Aggregate
@Getter
@NoArgsConstructor
public class Bar {

  @AggregateIdentifier
  private String fooIdentifier;

  private String barProperty;

  @CommandHandler
  public void on(UpdateBarCommand command) {

    apply(BarUpdatedEvent.builder()
      .fooIdentifier(this.fooIdentifier)
      .barProperty(command.getBarProperty())
      .build());
  }

  @EventSourcingHandler
  public void on(FooCreatedEvent event) {
    this.fooIdentifier = event.getFooIdentifier();
  }

  @EventSourcingHandler
  public void on(BarUpdatedEvent event) {
    this.barProperty = event.getBarProperty();
  }

}

Причина, по которой я пытался разделить, заключается в том, что мы хотели разделить базовый logi c (создание агрегата, в данном случае транспортного средства) из logi c, который происходит и обрабатывается в другом ограниченном контексте и отдельном микросервисе (передача с и на строительную площадку). Поскольку я не могу опубликовать sh событие создания (CommandHandler в конструкторе, последовательность 0) для одного и того же агрегированного идентификатора, но с другим агрегатным типом дважды, я не смог полностью разделить два состояния.

Итак, мои единственные варианты верны теперь будет то, что я представил выше, или использовать создание второго агрегата, чтобы установить другой агрегатный идентификатор, но также добавить внутренне агрегатный идентификатор первого агрегата, чтобы позволить публиковать события с информацией агрегатид первого в качестве ссылочного идентификатора . Чтобы эта работа работала, мне пришлось бы сохранить проекцию для сопоставления между двумя идентификаторами, что тоже выглядит не очень хорошо.

Заранее спасибо, Ларс Каршен

1 Ответ

0 голосов
/ 29 июня 2020

Очень интересное решение придумал Ларс. Не могу сказать, что я когда-либо разделял Aggregate logi c в таком поместье, что одна служба создает его, а другая загружает те же события, чтобы воссоздать это состояние в своей собственной форме.

против того, как фреймворк аксонов предполагает использование агрегатов, или это жизнеспособный вариант использования?

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

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

Из вашего описания я извлеку то, что у вас есть нечто, называемое агрегатом Vehicle, который переходит в разные состояния. Разве Polymorphi c Aggregate не было бы решением, которое вы ищете? Таким образом, у вас может быть родительский агрегат Vehicle со всеми основными функциями и, при необходимости, более конкретными реализациями c? Тем не менее, это может не полностью соответствовать вашему решению, в чем я не уверен, учитывая ваше описание.

Итак, я собираюсь добавить третий указатель, который, на мой взгляд, важно выделить:

Поскольку я не могу опубликовать sh событие создания (CommandHandler в конструкторе, последовательность 0) для одного и того же совокупного идентификатора, но для другого агрегатного типа дважды, я не смог полностью разделить два состояния.

Эта строка предполагает, что вы хотите повторно использовать Aggregate Identifier между разными Aggregates, что также возвращается в заголовке вопроса. Как вы отметили, пары [совокупный идентификатор, порядковый номер] должны быть уникальными. Следовательно, повторное использование совокупного идентификатора для другого типа совокупности не является вариантом. Однако знайте, что Axon будет использовать метод toString вашего класса совокупного идентификатора для заполнения поля совокупного идентификатора. Если вы, таким образом, скорректируете метод toString(), включив в него тип агрегата, вы сможете сохранить требование уникальности и по-прежнему повторно использовать свой агрегатный идентификатор.

Например, метод toString для VehicleId класс, содержащий UUID, обычно выводит это:

  • 684ec9f4-b9f8-11ea-b3de-0242ac130004

Но если вы измените toString, чтобы включить агрегатный тип, вы бы получите это:

  • VehichleId[684ec9f4-b9f8-11ea-b3de-0242ac130004]

В заключение, я думаю, что есть три основных момента, которыми я хотел бы поделиться:

  1. Axon Framework не намеревался повторно использовать агрегированные потоки для воссоздания отдельных агрегатных типов.
  2. Polymoprhi c Агрегаты могут быть средством разрешения имеющегося у вас сценария.
  3. Требование уникальности [aggregateId, seqNo] может повторно использовать aggregateId, если метод toString добавляет / добавляет агрегатный тип к результат.

Надеюсь, это поможет тебе в твоем путешествии, Ларс. Пожалуйста, дайте мне знать, если вам кажется, что чего-то не хватает, или если я asp неправильно ответил на ваш вопрос.

...