DDDesigner

Длительные бизнес-процессы

Сага в DDD: координация между агрегатами

Сага координирует бизнес-процесс, который охватывает несколько агрегатов или ограниченных контекстов и не помещается в одну транзакцию. Она хранит прогресс, отправляет команды, ждёт события и обрабатывает сбои. Сага — это модель бизнес-процесса, а не просто технический обработчик очереди.

Когда использовать сагу

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

  • Несколько команд выполняются последовательно
  • Процесс ждёт асинхронных событий
  • Важны timeout и retry
  • Выполненные шаги требуют компенсации

Оркестрация и хореография

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

Компенсация — бизнес-действие

Компенсация не является rollback базы. RefundPayment или ReleaseStock — новая бизнес-операция со своими правилами, сбоями и аудитом.

Сага, политика или простой обработчик события?

Политика обычно является реакцией без состояния: после PaymentReceived отправить письмо. Сага нужна, когда системе нужно помнить, на каком шаге находится процесс, ждать позднее событие, контролировать тайм-аут, повторять шаг или выбирать следующее действие по нескольким результатам.

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

Состояние, корреляция и идемпотентность

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

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

Оркестрация и хореография на практике

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

Выбирайте подход по сложности и ответственности процесса, а не по лозунгу. Если бизнесу нужно одно место, где видны сроки, компенсации и критерии завершения, оркестрация обычно понятнее.

Сбои, повторы и компенсации

Повтор подходит для временной технической ошибки, например кратковременного сетевого сбоя. Компенсация — новое бизнес-действие, которое отменяет или уравновешивает уже принятый факт: RefundPayment или ReleaseReservedStock. У него есть собственные права, инварианты, ошибки и аудит.

Компенсировать можно не всё. Некоторые действия необратимы, а некоторые требуют ручной проверки. Такие состояния нужно моделировать явно, а не прятать за общим словом «откат». Сага может создать событие о провале процесса, сохранив факты, которые уже произошли.

Чек-лист проверки саги

Сага готова к реализации, когда явно описаны стартовое событие, переходы состояния, команды, ожидаемые события, тайм-ауты и пути ошибок.

  • Какой бизнес-процесс принадлежит саге?
  • Что запускает и завершает его?
  • Как коррелируются экземпляры?
  • Какие шаги можно повторять?
  • Какие ошибки требуют компенсации или человека?
  • Как обрабатываются дубли и поздние сообщения?
  • Видит ли оператор зависший экземпляр?

DDDesigner

Пример: выполнение заказа между контекстами

После OrderPlaced Сага выполнения заказа просит Inventory зарезервировать товар, а Payments — списать деньги. Она хранит идентификаторы заказа и процесса, ждёт оба результата и корректно обрабатывает повторные сообщения. Если оплата не прошла после резервирования, сага отправляет ReleaseStock и фиксирует компенсацию. Если провайдер недоступен дольше установленного срока, процесс переходит в состояние ручной проверки, а не делает вид, что транзакция откатилась. После успеха Inventory, Payments и Shipping сага отправляет ScheduleDelivery и публикует FulfillmentCompleted.

Начать бесплатно