Короткий ответ
При частичном выполнении цепочки нужно явно спроектировать компенсирующие транзакции для каждого завершённого шага и оркестрацию, которая гарантированно доводит процесс до согласованного финального состояния; единого шаблона компенсации нет — для каждого шага она проектируется индивидуально исходя из его обратимости.
Как это работает подробнее
Компенсация — отдельная бизнес-операция, обратная по смыслу прямому действию; не каждое действие обратимо в строгом смысле, и для таких шагов проектируют смягчающее действие либо откладывают необратимый шаг на конец цепочки.
Полный набор компенсаций повышает надёжность процесса, но требует значительных усилий разработки и тестирования каждой точки отказа; упрощённый подход (алерт дежурному вместо автоматической компенсации) снижает инженерные затраты, но увеличивает operational burden и риск человеческой ошибки. Критерий выбора — частота ожидаемых частичных отказов и стоимость ошибки при неправильной ручной компенсации.
Пример кода
Цепочка: Payment.charge -> Inventory.reserve -> Shipping.schedule
Отказ на Shipping.schedule после успешных Payment и Inventory:
компенсация 2: Inventory.release_reservation
компенсация 1: Payment.refund
Оркестратор выполняет компенсации в обратном порядке и фиксирует финальный статус
заказа как "cancelled_after_partial_failure", с логированием для аудита.Что использовать на практике
- Практика. Оркестратор должен переживать собственные перезапуски — состояние прогресса Saga хранится персистентно; критичен мониторинг «зависших» процессов и алертинг для ручного вмешательства, когда автоматическая компенсация сама не срабатывает.
Подводные камни
- Риск. Проектировать только «счастливый путь» и добавлять компенсации постфактум после инцидента; размещать необратимые побочные эффекты в середине цепочки, а не в её конце.