From 65d156180391bb54622a4337134d6c451e137b8a Mon Sep 17 00:00:00 2001 From: Moritz Date: Mon, 15 Dec 2025 13:22:35 +0100 Subject: [PATCH] fix: correct return_notifications? logic to prevent missed notifications Fix the logic for return_notifications? in create_cycles --- lib/mv/membership_fees/cycle_generator.ex | 25 ++++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/mv/membership_fees/cycle_generator.ex b/lib/mv/membership_fees/cycle_generator.ex index f2539c0..1019a84 100644 --- a/lib/mv/membership_fees/cycle_generator.ex +++ b/lib/mv/membership_fees/cycle_generator.ex @@ -216,16 +216,16 @@ defmodule Mv.MembershipFees.CycleGenerator do end # Execute function within transaction and return normalized result - # When not in transaction, create_cycles returns {:ok, cycles, notifications} - # When in transaction, create_cycles returns {:ok, cycles} (notifications handled by Ash) + # When in transaction, create_cycles returns {:ok, cycles, notifications} + # When not in transaction, create_cycles returns {:ok, cycles} defp execute_within_transaction(fun) do case fun.() do {:ok, result, notifications} when is_list(notifications) -> - # Return result and notifications separately (not in transaction case) + # In transaction case: return result and notifications separately {result, notifications} {:ok, result} -> - # In transaction case: notifications handled by Ash automatically + # Not in transaction case: notifications handled by Ash automatically {result, []} {:error, reason} -> @@ -234,11 +234,11 @@ defmodule Mv.MembershipFees.CycleGenerator do end # Normalize function result to consistent format - # When in transaction, create_cycles returns {:ok, cycles} (notifications handled by Ash) - # When not in transaction, create_cycles returns {:ok, cycles, notifications} + # When in transaction, create_cycles returns {:ok, cycles, notifications} + # When not in transaction, create_cycles returns {:ok, cycles} defp normalize_fun_result({:ok, result, _notifications}) do - # This case should not occur when in transaction (create_cycles handles it) - # But handle it for safety + # In transaction case: notifications will be sent after outer transaction commits + # Return in same format as non-transaction case for consistency {:ok, result} end @@ -388,9 +388,10 @@ defmodule Mv.MembershipFees.CycleGenerator do end defp create_cycles(cycle_starts, member_id, fee_type_id, amount) do - # If already in a transaction, let Ash handle notifications automatically - # Otherwise, return notifications to send them after transaction commits - return_notifications? = not Repo.in_transaction?() + # Always return notifications when in a transaction (required by Ash) + # When not in transaction, Ash handles notifications automatically + # When in transaction, we must return notifications and send them after commit + return_notifications? = Repo.in_transaction?() results = Enum.map(cycle_starts, fn cycle_start -> @@ -426,7 +427,7 @@ defmodule Mv.MembershipFees.CycleGenerator do # Return cycles and notifications to be sent after transaction commits {:ok, successful_cycles, all_notifications} else - # Notifications are handled automatically by Ash when in transaction + # Not in transaction: Ash handles notifications automatically {:ok, successful_cycles} end else