defmodule Ecto.Adapters.FoundationDB.EctoAdapterTransaction do @moduledoc false alias Ecto.Adapters.FoundationDB alias EctoFoundationDB.Layer.Tx @behaviour Ecto.Adapter.Transaction @rollback :__ectofdbtxrollback__ @doc """ Runs the given function inside a transaction. Returns `{:ok, value}` if the transaction was successful where `value` is the value return by the function or `{:error, value}` if the transaction was rolled back where `value` is the value given to `rollback/1`. """ @impl true def transaction(_adapter_meta, options, function) when is_function(function, 0) do tenant = assert_tenancy!(options) FoundationDB.transactional(tenant, fn -> function.() end) catch {@rollback, value} -> {:error, value} end def transaction(_adapter_meta, options, function) when is_function(function, 1) do tenant = assert_tenancy!(options) FoundationDB.transactional(tenant, fn repo -> function.(repo) end) catch {:__ectofdbtxrollback__, value} -> {:error, value} end @doc """ Returns true if the given process is inside a transaction. """ @impl true def in_transaction?(_adapter_meta) do Tx.in_tx?() end @doc """ Rolls back the current transaction. The transaction will return the value given as `{:error, value}`. See `c:Ecto.Repo.rollback/1`. """ @impl true def rollback(adapter_meta, value) do if in_transaction?(adapter_meta) do throw({@rollback, value}) end end defp assert_tenancy!(options) do case Keyword.get(options, :prefix) do nil -> raise "Tenant required" tenant -> tenant end end end