Fix: Don't cache nil in default_role_id to prevent bootstrap issues

- 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 committed by Simon
parent 8e519d643d
commit 793a66639a
Signed by: simon
GPG key ID: 40E7A58C4AA1EDB2

View file

@ -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 ->