Удалить ссылочные элементы из агрегата

У меня вопрос по следующей ситуации. Допустим, у нас есть 2 домена с 2 агрегатами. Домен A и домен B — это разные микросервисы.

  1. Домен A – совокупность продуктов
  2. Домен B - совокупность магазинов

В нашем дизайне мы решаем, что домен A ничего не знает о домене B. В домене B каждый агрегат магазина имеет ссылку на один или несколько продуктов (товаров, которые можно продать).

Если мы хотим удалить продукт, мы можем отправить команду RemoveProductCommand в домен A — совокупность продуктов.

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

Я уже думал об этом и вижу 4 возможных варианта:

  1. Прослушивайте агрегаты магазина для ProductRemovedEvent, а затем удаляйте ссылку на продукт из магазина. Смиритесь с тем, что эта теория может привести к ситуации, когда продукт нельзя будет удалить, и он все еще будет в списке продаж магазина.

  2. Создайте SAGA в домене A и сначала удалите товары из магазинов, прежде чем пометить продукт как удаленный. Если обработка Saga не удалась, то все статусы магазина должны быть восстановлены путем отправки некоторых команд восстановления уже измененным агрегатам магазина. Чтобы узнать, какой магазин ссылается на продукт, мы используем запрос запроса для получения этой информации.

  3. То же, что и маркер 2, но также хранит информацию о магазине (идентификаторы) в совокупности продуктов (productListedInShopList).

  4. Другие определения домена/агрегата (например, объединить их)

Любые предложения, как лучше всего решить эту проблему?


person Jasper Huzen    schedule 15.01.2020    source источник


Ответы (1)


Я за вариант 2, но:

"A не знает о домене B": второй вариант продвигает то, что B является восходящим, а A - нижестоящим (A зависит от B, поскольку A отправляет команды B и A подписывается на события B. Эти команды и события являются частью API B), а не наоборот. Но это нормально! А и В не зависят друг от друга.

Кроме того, я бы рассмотрел возможность введения концепции продукта в домен B. Например, ShopProduct. Этот агрегат может быть связан с вашими магазинами, обеспечивающими безопасность инвариантов (аналогично вашему пункту № 3) в модели домена B. Это отделит ваши ограниченные контексты: ShopProduct — это то, как ограниченный контекст Shop понимает эту Product концепцию. Это позволит вам запускать только модель предметной области B в качестве независимого приложения.

ProductRemovedEvent переводит Продукт (домен A) в состояние PENDING, например, REMOVING, и это событие запускает Saga.

Saga будет обмениваться данными между Product (домен A) и ShopProduct (домен B):

  • Получено событие ProductRemovedEvent и отправлена ​​команда в модель магазина
  • ProductRemovedFromAllShopsSuccessfully получен из магазина, и мы отправляем команду Product для обновления состояния до REMOVED
  • ProductRemovedFromAllShopsUnSuccessfully получено из Магазина, и мы отправляем команду Продукту, чтобы обновить состояние до некоторого состояния ошибки или исходного состояния, чтобы компенсировать это. ...
person Ivan Dugalic    schedule 16.01.2020
comment
Решение с некоторым состоянием ожидания и этим событием, запускающим сагу, ожидающую удаления продуктов, также является нашим текущим решением. Спасибо за ваше предложение. Я подожду, пока этот ответ будет отмечен как принятый, потому что я надеюсь увидеть другие возможные решения. Спасибо! - person Jasper Huzen; 17.01.2020