Axon Framework: отправить команду при совокупной нагрузке

Мы создаем систему микросервисов с помощью Axon Framework 4.1. В нашем домене у нас есть концепция меток, в которой мы можем прикреплять метки к другим объектам. Хотя ярлыки обычно создаются и управляются пользователем, некоторые из этих ярлыков являются «специальными» и должны быть жестко запрограммированы, но они также должны присутствовать в потоке событий.

У нас есть набор агрегатов, которые представляют объекты, которые можно пометить этими метками. Некоторые из этих агрегатов будут использоваться часто, в то время как другие могут использоваться нечасто или даже могут быть оставлены пользователем.

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

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

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

К сожалению, эта функция, похоже, отсутствует в Axon (пока) ????.

Есть ли другие (лучшие) способы добиться этого?


person jqno    schedule 25.07.2019    source источник


Ответы (1)


У меня есть идея, которая может вам в этом помочь.

Если я правильно понимаю вариант использования, «Метка» в вашей системе, которую пользователь может представить, но для которой также существует пара жестко запрограммированных версий, является Агрегатом. Исходя из этого предположения, я предлагаю с умом использовать агрегированный идентификатор, который вы используете.

Единственное, что Axon ожидает от вас, - это то, что Aggregate Identifier будет (или может быть преобразован в) String. Обычно для агрегированных идентификаторов используется UUID, что является разумным первым запуском. Однако вы можете обернуть это UUID в объект с типизированным идентификатором. Взяв ваш агрегат "Label", он выберет LabelId.

Тем не менее, давайте сначала вернемся к проверке, существует ли данный агрегат «Метка» в потоке событий. Я думаю, у вас есть основания для беспокойства; чтение всего потока событий, чтобы выяснить, существует ли данный экземпляр Aggregate, является большой проблемой.

Однако EventStore можно запросить с помощью двух механизмов:

  1. Поток событий с заданного момента времени (например, что делает механизм TrackingToken).
  2. Поток событий для данного агрегированного экземпляра на основе агрегированного идентификатора.

Это второй вариант, который гораздо более идеален для вашего сценария. Просто запросите EventStore для данного Агрегатного идентификатора "Label". Если вы получили непустой поток событий, значит, он уже существует. И наоборот, если события не найдены, вы уверены, что необходимо ввести новый «Ярлык».

Суть здесь в том, чтобы заранее знать агрегатный идентификатор «метки», который возвращается к подходу String хранения для агрегированных идентификаторов с использованием типизированного LabelId. Что вы можете сделать, так это отклониться в объекте LabelId между настраиваемой меткой (здесь я бы выбрал UUID) и жестко запрограммированной меткой. Для последнего вы можете, например, иметь label-name плюс UUID / счетчик, если хотите.

Это гарантирует, что все события, опубликованные с жестко запрограммированной «метки», будут иметь совокупный идентификатор, который вы можете ожидать во время запуска.

Надеюсь, это ясно и все, если нет, прокомментируйте мой ответ ниже.

person Steven    schedule 05.08.2019
comment
Запрос EventStore кажется хорошей идеей для решения другой проблемы. Немного света: у нас есть 1 агрегат для каждого экземпляра документа, который управляет всеми метками для этого документа. Этот агрегат должен генерировать дополнительные события для недавно добавленных жестко запрограммированных меток. Мы могли бы запросить БД обо всех таких агрегатах управления и отправить им команду, но мы ищем и надеемся на лучший способ :) - person jhkuperus; 05.08.2019
comment
Ах, облом, так что мой ответ довольно четко не решает вашу проблему, поскольку мы говорим об агрегатном члене, а не об агрегатном корне. То, что вы предлагаете в конце вашего исходного вопроса, своего рода ловушку в процессе загрузки агрегатов, однако, я не уверен, следует добавить в структуру. Мое чутье склоняется к тому факту, что немногие люди будут использовать это (я, очевидно, могу ошибаться в этом). Если вы собираетесь создать это самостоятельно, я бы предложил тем или иным образом обернуть класс Aggregate Repository. Как ты думаешь @jhkuperus? - person Steven; 05.08.2019
comment
Я мог бы попробовать и посмотреть, насколько велико это влияние. Мы могли бы изучить концепцию в моей ветке фреймворка и обсудить ее. На данный момент мы собираемся проверять версию непосредственно перед выполнением определенных CommandHandler и генерировать события перед обработкой фактической команды. - person jhkuperus; 06.08.2019