* есть процесс покупки товара, он выполняется в транзакции
* процесс (функция) вызывает разные модули (функции) которые в свою очередь вызывают другие модули и где-то может произойти вызов внешнего АПИ, рассылка событий, писем и т.п.
* Вызов АПИ: может быть отправка запроса по сети либо добавление задачи в БД (в той же транзакции/или отдельной?) и запуск внешнего воркера на выполнение этой задачи.
Как сделать целостность всего процесса с вызовом АПИ и т.п., если транзакция оборвется в какой-то момент?
Так же сам АПИ может бросить исключение.
Рассылку событий можно убрать в конец, когда произойдет коммит, т.к. они не влияют на процесс.
Письма и задачи можно держать в той же тразакции, и при ролбеке они откатятся. Но воркеры будут запущены для задач которых нет, видимо они должны ждать какое-то время, или быть демонами (запущенными постоянно).
Если были какие-то внешние вызовы, эту информацию нужно где-то сохранять, и если возникла ошибка, после ролбека дергать код который будет откатывать внешний вызов и т.п.
Итого: для этого нужно все делать в одной транзакции, и возможность добавлять тригеры на commit/rollback текущей транзакции. (рассуждения по ходу написания)
Это ещё без учета, что сервер может упасть.
Что если какой-то модуль бросил исключение, но это ожидаемо (except), тогда могут сохранится какие-то обломки от работы модуля. Использовать вложенные транзакции?, какие БД это поддерживают?
Таким образом, при ошибке в API транзакция в базе откатится.
Этот подход не учитывает вариант, когда сервер жестко упадёт между выполнением запроса к внешнему API и применением транзакции - в таком случае данные могут потеряться, но эта ситуация пренебрежимо маловероятна.