Fix: Don't cache nil in default_role_id to prevent bootstrap issues
All checks were successful
continuous-integration/drone/push Build is passing

- Only cache non-nil role_id values to allow retry after role creation
- Prevents processes from being permanently stuck with nil if first call
  happens before the 'Mitglied' role exists
- Update documentation to explain bootstrap safety mechanism
This commit is contained in:
Moritz 2026-01-25 17:11:05 +01:00
parent 2d446f63ea
commit bdd2e6e103

View file

@ -445,6 +445,13 @@ defmodule Mv.Accounts.User do
The result is cached in the process dictionary to avoid repeated database queries The result is cached in the process dictionary to avoid repeated database queries
during high-volume user creation. The cache is invalidated on application restart. during high-volume user creation. The cache is invalidated on application restart.
## Bootstrap Safety
Only non-nil values are cached. If the role doesn't exist yet (e.g., before seeds run),
`nil` is not cached, allowing subsequent calls to retry after the role is created.
This prevents bootstrap issues where a process would be permanently stuck with `nil`
if the first call happens before the role exists.
## Performance Note ## Performance Note
This function makes one database query per process (cached in process dictionary). This function makes one database query per process (cached in process dictionary).
@ -464,6 +471,9 @@ defmodule Mv.Accounts.User do
@spec default_role_id() :: Ecto.UUID.t() | nil @spec default_role_id() :: Ecto.UUID.t() | nil
def default_role_id do def default_role_id do
# Cache in process dictionary to avoid repeated queries # Cache in process dictionary to avoid repeated queries
# IMPORTANT: Only cache non-nil values to avoid bootstrap issues.
# If the role doesn't exist yet (e.g., before seeds run), we don't cache nil
# so that subsequent calls can retry after the role is created.
case Process.get({__MODULE__, :default_role_id}) do case Process.get({__MODULE__, :default_role_id}) do
nil -> nil ->
role_id = role_id =
@ -472,7 +482,8 @@ defmodule Mv.Accounts.User do
_ -> nil _ -> nil
end end
Process.put({__MODULE__, :default_role_id}, role_id) # Only cache non-nil values to allow retry if role is created later
if role_id, do: Process.put({__MODULE__, :default_role_id}, role_id)
role_id role_id
cached_role_id -> cached_role_id ->