Rolling back on failure when using multiple databases using Ecto.Multi

Hello, I’m using Ecto for a project or mine and I’m running into issues with the rollback not working with a failed Ecto.Multi transaction that spans multiple databases. Is this not possible? Am I missing something?

Here’s a bit clearer example:

Multi.new
|> Multi.run(:db1, fn _, _ -> ModuleA.does_some_data_transformation_in_a_transaction_on_repo1() end)
|> Multi.run(:db2, fn _, _ -> ModuleB.does_some_data_transformation_in_a_transaction_on_repo2() end)
|> Multi.run(:db3, fn _, _ -> ModuleC.does_some_data_transformation_in_a_transaction_on_repo3() end)
|> Repo3.transaction()

If the :db3 step fails the other two transactions aren’t rolled back. Is there a way to achieve this?

Ecto multi works by utilizing underlying database transaction mechanics, not by adding its own. Cross database transactions are not possible. You may want to check out something like https://medium.com/nebo-15/introducing-sage-a-sagas-pattern-implementation-in-elixir-3ad499f236f6 which can implement a notion of rolling back that isn’t dependent on database level transactions.

3 Likes