Я вижу два аспекта, которые следует учитывать в вашем вопросе:
Аспект DDD: типы событий и то, что вы с ними делаете
Технический аспект: как его надежно реализовать
Что касается типов событий, я бы сказал, что события, которые обычно остаются в границах ограниченного контекста (часто называемые событиями домена) несут много информации. Потенциально большая часть состояния Агрегата. Если вы используете CQRS, они используются для создания модели чтения. События, которые пересекают границы B C, иногда называют событиями интеграции, и они должны нести как можно меньше данных (потенциально, только глобальные идентификаторы, такие как CustomerId, OrderId). Причина в том, что каждое дополнительное свойство, которое вы добавляете, является дополнительной связью между издателем B C и BC подписчика, что вы хотите минимизировать.
Я бы сказал, что это различие между типами событий может привести к разным техническим решениям, но я согласен с вами, что этого не должно быть, если вы найдете решение, которое хорошо работает для обоих случаев.
Предлагаемое вами решение правильное. Он очень похож на функцию Outbox в NServiceBus , которая в основном заботится обо всем этом за вас.
Другой подход, который я использовал, если ваш брокер сообщений поддерживает его, - это то, что Azure Service Bus вызывает Отправить через . С помощью этой функции вы можете публиковать sh событий через вашу собственную очередь, но отправка будет зафиксирована транзакционно с удалением входящего сообщения из очереди. Это означает, что если по какой-то причине обрабатываемое вами сообщение не было успешно удалено из очереди (исключение обновления БД, брокер недоступен и т. Д. c) и, следовательно, оно будет повторено, вы точно знаете, что события не будут будут отправлены, и вы можете безопасно опубликовать sh их снова во время повторной попытки. Это упрощает идемпотентные операции и позволяет избежать публикации фантомных сообщений.