@@ -2180,6 +2180,8 @@ defmodule Ecto.Repo do
21802180 @ doc """
21812181 Runs the given function or `Ecto.Multi` inside a transaction.
21822182
2183+ Deprecated in favor of `c:transact/2`.
2184+
21832185 ## Use with function
21842186
21852187 `c:transaction/2` can be called with both a function of arity
@@ -2209,42 +2211,7 @@ defmodule Ecto.Repo do
22092211 A successful transaction returns the value returned by the function
22102212 wrapped in a tuple as `{:ok, value}`.
22112213
2212- ### Nested transactions
2213-
2214- If `c:transaction/2` is called inside another transaction, the function
2215- is simply executed, without wrapping the new transaction call in any
2216- way. If there is an error in the inner transaction and the error is
2217- rescued, or the inner transaction is rolled back, the whole outer
2218- transaction is aborted, guaranteeing nothing will be committed.
2219-
2220- Below is an example of how rollbacks work with nested transactions:
2221-
2222- {:error, :rollback} =
2223- MyRepo.transaction(fn ->
2224- {:error, :posting_not_allowed} =
2225- MyRepo.transaction(fn ->
2226- # This function call causes the following to happen:
2227- #
2228- # * the transaction is rolled back in the database,
2229- # * code execution is stopped within the current function,
2230- # * and the value, passed to `rollback/1` is returned from
2231- # `MyRepo.transaction/1` as the second element in the error
2232- # tuple.
2233- #
2234- MyRepo.rollback(:posting_not_allowed)
2235-
2236- # `rollback/1` stops execution, so code here won't be run
2237- end)
2238-
2239- # The transaction here is now aborted and any further
2240- # operation will raise an exception.
2241- end)
2242-
2243- See the ["Aborted transactions"](`c:transaction/2#aborted-transactions`) section for more examples of aborted
2244- transactions and how to handle them.
2245-
2246- In practice, managing nested transactions can become complex quickly.
2247- For this reason, Ecto provides `Ecto.Multi` for composing transactions.
2214+ See `c:transact/2` for further considerations.
22482215
22492216 ## Use with Ecto.Multi
22502217
@@ -2265,63 +2232,6 @@ defmodule Ecto.Repo do
22652232
22662233 Explore the `Ecto.Multi` documentation to learn more and find detailed examples.
22672234
2268- ## Aborted transactions
2269-
2270- When an operation inside a transaction fails, the transaction is aborted in the database.
2271- For instance, if you attempt an insert that violates a unique constraint, the insert fails
2272- and the transaction is aborted. In such cases, any further operation inside the transaction
2273- will raise exceptions.
2274-
2275- Take the following transaction as an example:
2276-
2277- Repo.transaction(fn repo ->
2278- case repo.insert(changeset) do
2279- {:ok, post} ->
2280- repo.insert(%Status{value: "success"})
2281-
2282- {:error, changeset} ->
2283- repo.insert(%Status{value: "failure"})
2284- end
2285- end)
2286-
2287- If the changeset is valid, but the insert operation fails due to a database constraint,
2288- the subsequent `repo.insert(%Status{value: "failure"})` operation will raise an exception
2289- because the database has already aborted the transaction and thus making the operation invalid.
2290- In Postgres, the exception would look like this:
2291-
2292- ** (Postgrex.Error) ERROR 25P02 (in_failed_sql_transaction) current transaction is aborted, commands ignored until end of transaction block
2293-
2294- If the changeset is invalid before it reaches the database due to a validation error,
2295- no statement is sent to the database, an `:error` tuple is returned, and `repo.insert(%Status{value: "failure"})`
2296- operation will execute as usual.
2297-
2298- We have two options to deal with such scenarios:
2299-
2300- If you don't want to change the semantics of your code, you can also use the savepoints
2301- feature by passing the `:mode` option like this: `repo.insert(changeset, mode: :savepoint)`.
2302- In case of an exception, the transaction will rollback to the savepoint and prevent
2303- the transaction from failing.
2304-
2305- Another alternative is to handle this operation outside of the transaction.
2306- For example, you can choose to perform an explicit `repo.rollback` call in the
2307- `{:error, changeset}` clause and then perform the `repo.insert(%Status{value: "failure"})` outside
2308- of the transaction. You might also consider using `Ecto.Multi`, as they automatically
2309- rollback whenever an operation fails.
2310-
2311- ## Working with processes
2312-
2313- The transaction is per process. A separate process started inside a
2314- transaction won't be part of the same transaction and will use a separate
2315- connection altogether.
2316-
2317- When using the `Ecto.Adapters.SQL.Sandbox` in tests, while it may be
2318- possible to share the connection between processes, the parent process
2319- will typically hold the connection until the transaction completes. This
2320- may lead to a deadlock if the child process attempts to use the same connection.
2321- See the docs for
2322- [`Ecto.Adapters.SQL.Sandbox`](https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html)
2323- for more information.
2324-
23252235 ## Options
23262236
23272237 See the ["Shared options"](#module-shared-options) section at the module
0 commit comments