refactor(types): bind intentionally discarded side-effecting results

This commit is contained in:
Moritz 2026-06-02 11:42:57 +02:00
parent 04ab05f556
commit 848f0cd013
12 changed files with 24 additions and 22 deletions

View file

@ -939,7 +939,7 @@ defmodule Mv.Membership.Member do
# Already in transaction: use advisory lock directly # Already in transaction: use advisory lock directly
# Returns {:ok, notifications} - notifications should be returned to after_action hook # Returns {:ok, notifications} - notifications should be returned to after_action hook
defp regenerate_cycles_in_transaction(member, today, lock_key) do defp regenerate_cycles_in_transaction(member, today, lock_key) do
EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key]) _ = EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key])
do_regenerate_cycles_on_type_change(member, today, skip_lock?: true) do_regenerate_cycles_on_type_change(member, today, skip_lock?: true)
end end
@ -947,7 +947,7 @@ defmodule Mv.Membership.Member do
# Returns {:ok, notifications} - notifications should be sent by caller (e.g., via after_action) # Returns {:ok, notifications} - notifications should be sent by caller (e.g., via after_action)
defp regenerate_cycles_new_transaction(member, today, lock_key) do defp regenerate_cycles_new_transaction(member, today, lock_key) do
Repo.transaction(fn -> Repo.transaction(fn ->
EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key]) _ = EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key])
case do_regenerate_cycles_on_type_change(member, today, skip_lock?: true) do case do_regenerate_cycles_on_type_change(member, today, skip_lock?: true) do
{:ok, notifications} -> {:ok, notifications} ->
@ -1093,7 +1093,7 @@ defmodule Mv.Membership.Member do
initiator: initiator initiator: initiator
) do ) do
{:ok, cycles, notifications} -> {:ok, cycles, notifications} ->
send_notifications_if_any(notifications) _ = send_notifications_if_any(notifications)
log_cycle_generation_success(member, cycles, notifications, log_cycle_generation_success(member, cycles, notifications,
sync: true, sync: true,
@ -1112,7 +1112,7 @@ defmodule Mv.Membership.Member do
initiator: initiator initiator: initiator
) do ) do
{:ok, cycles, notifications} -> {:ok, cycles, notifications} ->
send_notifications_if_any(notifications) _ = send_notifications_if_any(notifications)
log_cycle_generation_success(member, cycles, notifications, log_cycle_generation_success(member, cycles, notifications,
sync: false, sync: false,

View file

@ -37,6 +37,7 @@ defmodule Mv.Membership.Member.Changes.UnrelateUserWhenArgumentNil do
{:ok, %{user: user}} when not is_nil(user) -> {:ok, %{user: user}} when not is_nil(user) ->
# User's :update action only accepts [:email]; use :update_user so # User's :update action only accepts [:email]; use :update_user so
# manage_relationship(:member, ..., on_missing: :unrelate) runs and clears member_id. # manage_relationship(:member, ..., on_missing: :unrelate) runs and clears member_id.
_ =
user user
|> Ash.Changeset.for_update(:update_user, %{member: nil}, domain: Mv.Accounts) |> Ash.Changeset.for_update(:update_user, %{member: nil}, domain: Mv.Accounts)
|> Ash.update(domain: Mv.Accounts, actor: actor, authorize?: false) |> Ash.update(domain: Mv.Accounts, actor: actor, authorize?: false)

View file

@ -122,7 +122,7 @@ defmodule Mv.MembershipFees.CycleGenerator do
lock_key = Member.advisory_lock_key_for_member_id(member.id) lock_key = Member.advisory_lock_key_for_member_id(member.id)
Repo.transaction(fn -> Repo.transaction(fn ->
EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key]) _ = EctoSQL.query!(Repo, "SELECT pg_advisory_xact_lock($1)", [lock_key])
case do_generate_cycles(member, today, opts) do case do_generate_cycles(member, today, opts) do
{:ok, cycles, notifications} -> {:ok, cycles, notifications} ->
@ -220,7 +220,7 @@ defmodule Mv.MembershipFees.CycleGenerator do
defp process_member_cycle_generation(member, today) do defp process_member_cycle_generation(member, today) do
case generate_cycles_for_member(member, today: today) do case generate_cycles_for_member(member, today: today) do
{:ok, _cycles, notifications} = ok -> {:ok, _cycles, notifications} = ok ->
send_notifications_for_batch_job(notifications) _ = send_notifications_for_batch_job(notifications)
{member.id, ok} {member.id, ok}
{:error, _reason} = err -> {:error, _reason} = err ->

View file

@ -37,6 +37,7 @@ defmodule Mv.Vereinfacht.SyncFlash do
def create_table! do def create_table! do
# :public so any process can write (SyncContact runs in LiveView/Ash transaction process, # :public so any process can write (SyncContact runs in LiveView/Ash transaction process,
# not the process that created the table). :protected would restrict writes to the creating process. # not the process that created the table). :protected would restrict writes to the creating process.
_ =
if :ets.whereis(@table) == :undefined do if :ets.whereis(@table) == :undefined do
:ets.new(@table, [:set, :public, :named_table]) :ets.new(@table, [:set, :public, :named_table])
end end

View file

@ -30,8 +30,8 @@ defmodule MvWeb.SignInLive do
# Set both backend-specific and global locale so Gettext.get_locale/0 and # Set both backend-specific and global locale so Gettext.get_locale/0 and
# Gettext.get_locale/1 both return the correct value (important for the # Gettext.get_locale/1 both return the correct value (important for the
# language-selector `selected` attribute in Layouts.public_page). # language-selector `selected` attribute in Layouts.public_page).
Gettext.put_locale(MvWeb.Gettext, locale) _ = Gettext.put_locale(MvWeb.Gettext, locale)
Gettext.put_locale(locale) _ = Gettext.put_locale(locale)
# Prepend DE-specific overrides when locale is German so that components # Prepend DE-specific overrides when locale is German so that components
# without _gettext support (e.g. HorizontalRule) still render in German. # without _gettext support (e.g. HorizontalRule) still render in German.

View file

@ -16,8 +16,8 @@ defmodule MvWeb.SignOutLive do
@impl true @impl true
def mount(_params, session, socket) do def mount(_params, session, socket) do
locale = session["locale"] || Application.get_env(:mv, :default_locale, "de") locale = session["locale"] || Application.get_env(:mv, :default_locale, "de")
Gettext.put_locale(MvWeb.Gettext, locale) _ = Gettext.put_locale(MvWeb.Gettext, locale)
Gettext.put_locale(locale) _ = Gettext.put_locale(locale)
club_name = club_name =
case Membership.get_settings() do case Membership.get_settings() do

View file

@ -52,7 +52,7 @@ defmodule MvWeb.GlobalSettingsLive do
# Get locale from session; same fallback as router/LiveUserAuth (respects config :default_locale in test) # Get locale from session; same fallback as router/LiveUserAuth (respects config :default_locale in test)
locale = session["locale"] || Application.get_env(:mv, :default_locale, "de") locale = session["locale"] || Application.get_env(:mv, :default_locale, "de")
Gettext.put_locale(MvWeb.Gettext, locale) _ = Gettext.put_locale(MvWeb.Gettext, locale)
actor = MvWeb.LiveHelpers.current_actor(socket) actor = MvWeb.LiveHelpers.current_actor(socket)
custom_fields = load_custom_fields(actor) custom_fields = load_custom_fields(actor)

View file

@ -326,7 +326,7 @@ defmodule MvWeb.MembershipFeeTypeLive.Form do
case submit_form(socket.assigns.form, params, actor) do case submit_form(socket.assigns.form, params, actor) do
{:ok, membership_fee_type} -> {:ok, membership_fee_type} ->
notify_parent({:saved, membership_fee_type}) _ = notify_parent({:saved, membership_fee_type})
socket = socket =
socket socket

View file

@ -165,7 +165,7 @@ defmodule MvWeb.RoleLive.Form do
case MvWeb.LiveHelpers.submit_form(socket.assigns.form, role_params, actor) do case MvWeb.LiveHelpers.submit_form(socket.assigns.form, role_params, actor) do
{:ok, role} -> {:ok, role} ->
notify_parent({:saved, role}) _ = notify_parent({:saved, role})
redirect_path = redirect_path =
if socket.assigns.return_to == "show" do if socket.assigns.return_to == "show" do

View file

@ -734,7 +734,7 @@ defmodule MvWeb.UserLive.Form do
end end
defp handle_save_success(socket, updated_user) do defp handle_save_success(socket, updated_user) do
notify_parent({:saved, updated_user}) _ = notify_parent({:saved, updated_user})
action = get_action_name(socket.assigns.form.source.type) action = get_action_name(socket.assigns.form.source.type)

View file

@ -22,7 +22,7 @@ defmodule MvWeb.LiveHelpers do
def on_mount(:default, _params, session, socket) do def on_mount(:default, _params, session, socket) do
locale = session["locale"] || "de" locale = session["locale"] || "de"
Gettext.put_locale(locale) _ = Gettext.put_locale(locale)
# Browser timezone from LiveSocket connect params (set in app.js via Intl API) # Browser timezone from LiveSocket connect params (set in app.js via Intl API)
connect_params = socket.private[:connect_params] || %{} connect_params = socket.private[:connect_params] || %{}

View file

@ -188,7 +188,7 @@ defmodule MvWeb.Router do
get_locale_from_cookie(conn) || get_locale_from_cookie(conn) ||
extract_locale_from_headers(conn.req_headers) extract_locale_from_headers(conn.req_headers)
Gettext.put_locale(MvWeb.Gettext, locale) _ = Gettext.put_locale(MvWeb.Gettext, locale)
conn conn
|> put_session(:locale, locale) |> put_session(:locale, locale)