chore: fix return_notifications? behavior

This commit is contained in:
Zach Daniel 2023-04-13 01:41:19 -04:00
parent 911acdef5b
commit 81c9475e2e
5 changed files with 90 additions and 53 deletions

View file

@ -89,6 +89,7 @@ defmodule Ash.Actions.Create do
timeout: opts[:timeout],
upsert_identity: upsert_identity,
upsert_keys: upsert_keys,
return_notifications?: opts[:return_notifications?],
authorize?: authorize?,
actor: actor,
tenant: opts[:tenant],
@ -459,6 +460,7 @@ defmodule Ash.Actions.Create do
Keyword.get(request_opts, :transaction?, true) && action.transaction?,
timeout: request_opts[:timeout],
tracer: request_opts[:tracer],
return_notifications?: request_opts[:return_notifications?],
transaction_metadata: %{
type: :create,
metadata: %{

View file

@ -94,6 +94,7 @@ defmodule Ash.Actions.Destroy do
authorize?: authorize?,
actor: actor,
timeout: opts[:timeout] || changeset.timeout || Ash.Api.Info.timeout(api),
return_notifications?: opts[:return_notifications?],
tracer: opts[:tracer],
timeout: opts[:timeout],
tenant: opts[:tenant]
@ -327,6 +328,7 @@ defmodule Ash.Actions.Destroy do
transaction?:
Keyword.get(request_opts, :transaction?, true) && action.transaction?,
timeout: request_opts[:timeout],
return_notifications?: request_opts[:return_notifications?],
transaction_metadata: %{
type: :destroy,
metadata: %{

View file

@ -72,6 +72,7 @@ defmodule Ash.Actions.Update do
|> as_requests(resource, api, action,
changeset: changeset,
authorize?: authorize?,
return_notifications?: opts[:return_notifications?],
actor: actor,
timeout: opts[:timeout] || changeset.timeout || Ash.Api.Info.timeout(api),
tracer: opts[:tracer],
@ -460,6 +461,7 @@ defmodule Ash.Actions.Update do
transaction?:
Keyword.get(request_opts, :transaction?, true) && action.transaction?,
timeout: request_opts[:timeout],
return_notifications?: request_opts[:return_notifications?],
transaction_metadata: %{
type: :update,
metadata: %{

View file

@ -1563,32 +1563,51 @@ defmodule Ash.Changeset do
|> Enum.concat(changeset.action.touches_resources)
|> Enum.uniq()
Process.put(
:ash_after_transaction,
Process.get(:ash_after_transaction, []) ++ changeset.after_transaction
)
notify? =
if Process.get(:ash_started_transaction?) do
false
else
Process.put(:ash_started_transaction?, true)
true
end
resources
|> Enum.reject(&Ash.DataLayer.in_transaction?/1)
|> Ash.DataLayer.transaction(
fn ->
case run_around_actions(changeset, func) do
{:error, error} ->
Ash.DataLayer.rollback(changeset.resource, error)
try do
resources
|> Enum.reject(&Ash.DataLayer.in_transaction?/1)
|> Ash.DataLayer.transaction(
fn ->
case run_around_actions(changeset, func) do
{:error, error} ->
Ash.DataLayer.rollback(changeset.resource, error)
other ->
other
end
end,
changeset.timeout || :infinity,
opts[:transaction_metadata]
)
|> case do
{:ok, result} ->
result
other ->
other
end
end,
changeset.timeout || :infinity,
opts[:transaction_metadata]
)
|> case do
{:ok, {:ok, value, changeset, instructions}} ->
notifications =
if notify? && !opts[:return_notifications?] do
Enum.concat(
instructions[:notifications] || [],
Process.delete(:ash_notifications) || []
)
else
instructions[:notifications] || []
end
{:error, error} ->
{:error, error}
{:ok, value, changeset, Map.put(instructions, :notifications, notifications)}
{:error, error} ->
{:error, error}
end
after
if notify? do
Process.delete(:ash_started_transaction?)
end
end
end)
else
@ -1608,6 +1627,30 @@ defmodule Ash.Changeset do
end
end)
end
|> case do
{:ok, value, changeset, instructions} ->
if opts[:return_notifications?] do
{:ok, value, changeset, instructions}
else
if Process.get(:ash_started_transaction?) do
current_notifications = Process.get(:ash_notifications, [])
Process.put(
:ash_notifications,
current_notifications ++ (instructions[:notifications] || [])
)
{:ok, value, changeset, Map.put(instructions, :notifications, [])}
else
notifications = Ash.Notifier.notify(instructions[:notifications] || [])
{:ok, value, changeset, Map.put(instructions, :notifications, notifications)}
end
end
other ->
other
end
end
defp warn_on_transaction_hooks(_, [], _), do: :ok

View file

@ -100,10 +100,10 @@ defmodule Ash.Engine do
resources ->
notify? =
if Process.get(:ash_engine_started_transaction?) do
if Process.get(:ash_started_transaction?) do
false
else
Process.put(:ash_engine_started_transaction?, true)
Process.put(:ash_started_transaction?, true)
true
end
@ -124,20 +124,14 @@ defmodule Ash.Engine do
)
|> case do
{:ok, result} ->
saved_notifications = Process.delete(:ash_engine_notifications) || []
if notify? do
saved_notifications = Process.delete(:ash_notifications) || []
if opts[:return_notifications?] do
{:ok,
%{
result
| resource_notifications:
result.resource_notifications ++ saved_notifications
}}
else
remaining_notifications =
Ash.Notifier.notify(result.resource_notifications ++ saved_notifications)
remaining_notifications = result.resource_notifications ++ saved_notifications
{:ok, %{result | resource_notifications: remaining_notifications}}
else
{:ok, result}
end
{:error, error} ->
@ -145,7 +139,7 @@ defmodule Ash.Engine do
end
after
if notify? do
Process.delete(:ash_engine_started_transaction?)
Process.delete(:ash_started_transaction?)
end
end
end
@ -164,23 +158,17 @@ defmodule Ash.Engine do
|> case do
{:ok, %{resource_notifications: resource_notifications} = result} ->
notifications =
if opts[:return_notifications?] do
resource_notifications
if Process.get(:ash_started_transaction?) && !opts[:return_notifications?] do
current_notifications = Process.get(:ash_notifications, [])
Process.put(
:ash_notifications,
current_notifications ++ resource_notifications
)
[]
else
notifications = Ash.Notifier.notify(resource_notifications)
if Process.get(:ash_engine_started_transaction?) do
current_notifications = Process.get(:ash_engine_notifications, [])
Process.put(
:ash_engine_notifications,
current_notifications ++ notifications
)
[]
else
notifications
end
resource_notifications
end
{:ok, %{result | resource_notifications: notifications}}