diff --git a/lib/accounts/user.ex b/lib/accounts/user.ex index 7ec870b..bcaf506 100644 --- a/lib/accounts/user.ex +++ b/lib/accounts/user.ex @@ -445,6 +445,13 @@ defmodule Mv.Accounts.User do 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. + ## 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 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 def default_role_id do # 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 nil -> role_id = @@ -472,7 +482,8 @@ defmodule Mv.Accounts.User do _ -> nil 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 cached_role_id ->