Skip to content

Commit aa44483

Browse files
committed
improvement: add backwards compatibility for data layers returning only index metadata
1 parent dbc9d9f commit aa44483

File tree

4 files changed

+68
-31
lines changed

4 files changed

+68
-31
lines changed

lib/ash/actions/create/bulk.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1455,7 +1455,8 @@ defmodule Ash.Actions.Create.Bulk do
14551455
|> Ash.Actions.Update.Bulk.run_bulk_after_changes(
14561456
all_changes,
14571457
results,
1458-
changesets_by_index,
1458+
changesets_by_index, # This acts as changesets_by_ref for create
1459+
nil, # No index->ref mapping needed for create
14591460
changesets,
14601461
opts,
14611462
ref,

lib/ash/actions/destroy/bulk.ex

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2170,7 +2170,8 @@ defmodule Ash.Actions.Destroy.Bulk do
21702170
|> Ash.Actions.Update.Bulk.run_bulk_after_changes(
21712171
all_changes,
21722172
batch,
2173-
changesets_by_index,
2173+
changesets_by_index, # This acts as changesets_by_ref for destroy
2174+
nil, # No index->ref mapping needed for destroy
21742175
changesets,
21752176
opts,
21762177
ref,

lib/ash/actions/update/bulk.ex

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,13 +2147,15 @@ defmodule Ash.Actions.Update.Bulk do
21472147
end
21482148
end
21492149

2150-
defp index_changesets_by_ref(batch, context_key) do
2151-
Enum.reduce(batch, %{}, fn changeset, changesets_by_ref ->
2152-
Map.put(
2153-
changesets_by_ref,
2154-
changeset.context[context_key].ref,
2155-
changeset
2156-
)
2150+
defp index_changesets(batch, context_key) do
2151+
Enum.reduce(batch, {%{}, %{}}, fn changeset, {by_ref, by_index} ->
2152+
ref = changeset.context[context_key].ref
2153+
index = changeset.context[context_key].index
2154+
2155+
{
2156+
Map.put(by_ref, ref, changeset),
2157+
Map.put(by_index, index, ref)
2158+
}
21572159
end)
21582160
end
21592161

@@ -2529,7 +2531,7 @@ defmodule Ash.Actions.Update.Bulk do
25292531
end
25302532
end)
25312533

2532-
changesets_by_ref = index_changesets_by_ref(batch, context_key)
2534+
{changesets_by_ref, changesets_by_index} = index_changesets(batch, context_key)
25332535

25342536
batch =
25352537
batch
@@ -2686,7 +2688,7 @@ defmodule Ash.Actions.Update.Bulk do
26862688
end)
26872689
end
26882690

2689-
{batch, changesets_by_ref}
2691+
{batch, changesets_by_ref, changesets_by_index}
26902692
end
26912693

26922694
defp manage_relationships(updated, domain, changeset, engine_opts) do
@@ -2704,7 +2706,7 @@ defmodule Ash.Actions.Update.Bulk do
27042706
end
27052707

27062708
defp run_after_action_hooks(
2707-
{batch_results, changesets_by_ref},
2709+
{batch_results, changesets_by_ref, changesets_by_index},
27082710
opts,
27092711
domain,
27102712
ref,
@@ -2759,11 +2761,11 @@ defmodule Ash.Actions.Update.Bulk do
27592761
end
27602762
end)
27612763

2762-
{results, changesets_by_ref}
2764+
{results, changesets_by_ref, changesets_by_index}
27632765
end
27642766

27652767
defp process_results(
2766-
{batch, changesets_by_ref},
2768+
{batch, changesets_by_ref, changesets_by_index},
27672769
changes,
27682770
all_changes,
27692771
opts,
@@ -2780,6 +2782,7 @@ defmodule Ash.Actions.Update.Bulk do
27802782
all_changes,
27812783
batch,
27822784
changesets_by_ref,
2785+
changesets_by_index,
27832786
changesets,
27842787
opts,
27852788
ref,
@@ -2872,6 +2875,7 @@ defmodule Ash.Actions.Update.Bulk do
28722875
all_changes,
28732876
results,
28742877
changesets_by_ref,
2878+
changesets_by_index,
28752879
changesets,
28762880
opts,
28772881
ref,
@@ -2964,6 +2968,7 @@ defmodule Ash.Actions.Update.Bulk do
29642968
result,
29652969
changes[index],
29662970
changesets_by_ref,
2971+
changesets_by_index,
29672972
metadata_key,
29682973
ref_metadata_key
29692974
)
@@ -3573,17 +3578,39 @@ defmodule Ash.Actions.Update.Bulk do
35733578
changeset
35743579
end
35753580

3576-
defp result_matches_changes?(result, changes, changesets_by_ref, metadata_key, ref_metadata_key) do
3577-
if ref_metadata_key do
3581+
defp result_matches_changes?(result, changes, changesets_by_ref, changesets_by_index, metadata_key, ref_metadata_key) do
3582+
# For create/destroy operations, changesets_by_index may be nil and we use direct index matching
3583+
if is_nil(changesets_by_index) do
3584+
# Legacy behavior for create/destroy: direct index-based matching
3585+
result.__metadata__[metadata_key] in List.wrap(changes)
3586+
else
3587+
# New behavior for update operations: try ref first, then fallback to index->ref mapping
35783588
ref_key = result.__metadata__[ref_metadata_key]
35793589

3580-
changesets_by_ref
3581-
|> Map.get(ref_key)
3582-
|> ensure_changeset!(result, metadata_key, ref_metadata_key)
3590+
ref_key =
3591+
if ref_key do
3592+
ref_key
3593+
else
3594+
# Fallback: get ref from index mapping for backwards compatibility
3595+
index = result.__metadata__[metadata_key]
35833596

3584-
ref_key in List.wrap(changes)
3585-
else
3586-
result.__metadata__[metadata_key] in List.wrap(changes)
3597+
if index do
3598+
changesets_by_index[index]
3599+
else
3600+
nil
3601+
end
3602+
end
3603+
3604+
if ref_key do
3605+
changesets_by_ref
3606+
|> Map.get(ref_key)
3607+
|> ensure_changeset!(result, metadata_key, ref_metadata_key)
3608+
3609+
ref_key in List.wrap(changes)
3610+
else
3611+
# Final fallback to index-based matching if no ref available
3612+
result.__metadata__[metadata_key] in List.wrap(changes)
3613+
end
35873614
end
35883615
end
35893616

lib/ash/data_layer/ets/ets.ex

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,15 +1880,23 @@ defmodule Ash.DataLayer.Ets do
18801880
{:ok, result} ->
18811881
result =
18821882
if result_changeset.context[:bulk_update] do
1883-
result
1884-
|> Ash.Resource.put_metadata(
1885-
:bulk_update_index,
1886-
result_changeset.context.bulk_update.index
1887-
)
1888-
|> Ash.Resource.put_metadata(
1889-
:bulk_action_ref,
1890-
result_changeset.context.bulk_update.ref
1891-
)
1883+
result =
1884+
result
1885+
|> Ash.Resource.put_metadata(
1886+
:bulk_update_index,
1887+
result_changeset.context.bulk_update.index
1888+
)
1889+
1890+
# For testing backwards compatibility, allow skipping ref metadata
1891+
if Application.get_env(:ash, :test_bulk_index_only, false) do
1892+
result
1893+
else
1894+
Ash.Resource.put_metadata(
1895+
result,
1896+
:bulk_action_ref,
1897+
result_changeset.context.bulk_update.ref
1898+
)
1899+
end
18921900
else
18931901
result
18941902
end

0 commit comments

Comments
 (0)