1 comment

[ 4.1 ms ] story [ 15.6 ms ] thread
IMO Ecto.Multi is an anti-pattern.

It's just an internal DSL using builder pattern to create a pipeline running inside a client-side Ecto transaction.

Transactions should be avoided (especially the client-side ones), and in cases when they're absolutely needed - their run time should be reduced to a minimum, i.e. avoid long-running code inside a transaction in order not to block other processes using the same DB connection.

Some examples of non-DB related code usually called from inside client-side transaction:

- input validations / preconditions checks

- side-effects: sending emails / push notifications / etc.

- communicating with 3rd party services

The solution for this isn't easy, usually involves application-specific knowledge, or using Saga pattern.

Ecto.Multi can be easily replaced by using "with" statement inside an Ecto transaction, as described in [1].

Unlike Ecto.Multi where each step has a label, when using "with" statement you don't know on which step the transaction failed. The solution is to use "tagged with statement" pattern like shown in [2].

The only advantages of Ecto.Multi are:

- dynamically-built transactions

- testability (but these tests are questionable anyway, after all you're not testing regular Elixir pipelines)

--

[1] https://medium.com/very-big-things/towards-maintainable-elix...

[2] https://dev.to/aloukissas/elixir-s-with-statement-is-fantast...