@@ -1160,17 +1160,28 @@ defmodule Phoenix.Sync.Writer do
11601160
11611161 @ txn_name { :__phoenix_sync__ , :txn }
11621162 @ txid_name { :__phoenix_sync__ , :txid }
1163+ @ txid_query "SELECT txid_current() as txid"
11631164
11641165 defp start_multi ( txn ) do
11651166 Ecto.Multi . new ( )
1167+ |> txid_step ( )
11661168 |> Ecto.Multi . put ( @ txn_name , txn )
1167- |> Ecto.Multi . run ( @ txid_name , fn repo , _ ->
1168- with { :ok , % { rows: [ [ txid ] ] } } <- repo . query ( "SELECT txid_current() as txid" ) do
1169+ end
1170+
1171+ defp txid_step ( multi \\ Ecto.Multi . new ( ) ) do
1172+ Ecto.Multi . run ( multi , @ txid_name , fn repo , _ ->
1173+ with { :ok , % { rows: [ [ txid ] ] } } <- repo . query ( @ txid_query ) do
11691174 { :ok , txid }
11701175 end
11711176 end )
11721177 end
11731178
1179+ defp has_txid_step? ( multi ) do
1180+ multi
1181+ |> Ecto.Multi . to_list ( )
1182+ |> Enum . any? ( fn { name , _ } -> name == @ txid_name end )
1183+ end
1184+
11741185 defp apply_change ( multi , % Operation { } = op , % __MODULE__ { } = writer ) do
11751186 with { :ok , actions } <- mutation_actions ( op , writer ) ,
11761187 { :ok , action } <- Map . fetch ( actions , op . operation ) do
@@ -1455,18 +1466,53 @@ defmodule Phoenix.Sync.Writer do
14551466 end)
14561467 Plug.Conn.send_resp(conn, 400, Jason.encode!(error))
14571468 end
1469+
1470+ Also supports normal fun/0 or fun/1 style transactions much like
1471+ `Ecto.Repo.transaction/2`, returning the txid of the operation:
1472+
1473+ {:ok, txid, todo} =
1474+ Phoenix.Sync.Writer.transaction(fn ->
1475+ Repo.insert!(changeset)
1476+ end, Repo)
14581477 """
14591478 @ spec transaction ( Ecto.Multi . t ( ) , Ecto.Repo . t ( ) , keyword ( ) ) ::
14601479 { :ok , txid ( ) , Ecto.Multi . changes ( ) } | Ecto.Multi . failure ( )
14611480 def transaction ( multi , repo , opts \\ [ ] )
14621481
14631482 def transaction ( % Ecto.Multi { } = multi , repo , opts ) when is_atom ( repo ) do
1464- with { :ok , changes } <- repo . transaction ( multi , opts ) do
1483+ wrapped_multi =
1484+ if has_txid_step? ( multi ) do
1485+ multi
1486+ else
1487+ Ecto.Multi . prepend ( multi , txid_step ( ) )
1488+ end
1489+
1490+ with { :ok , changes } <- repo . transaction ( wrapped_multi , opts ) do
14651491 { txid , changes } = Map . pop! ( changes , @ txid_name )
14661492 { :ok , txid , changes }
14671493 end
14681494 end
14691495
1496+ def transaction ( fun , repo , opts ) when is_function ( fun ) and is_atom ( repo ) do
1497+ with { :ok , { txid , result } } <-
1498+ repo . transaction (
1499+ fn ->
1500+ % { rows: [ [ txid ] ] } = repo . query! ( @ txid_query )
1501+
1502+ result =
1503+ case fun do
1504+ fun0 when is_function ( fun0 , 0 ) -> fun . ( )
1505+ fun1 when is_function ( fun1 , 1 ) -> fun1 . ( repo )
1506+ end
1507+
1508+ { txid , result }
1509+ end ,
1510+ opts
1511+ ) do
1512+ { :ok , txid , result }
1513+ end
1514+ end
1515+
14701516 @ doc """
14711517 Extract the transaction id from changes returned from `Repo.transaction`.
14721518
0 commit comments