Instead of polling with Process.sleep in a loop, use a subscriber pattern with GenServer:
defmodule MyServer do
use GenServer
defstruct ready: false, subscribers: []
# Client API - blocks until ready
def wait_for_ready(opts \\ []) do
timeout = Keyword.get(opts, :timeout, 30_000)
GenServer.call(__MODULE__, :wait_for_ready, timeout)
end
# Server callbacks
def handle_call(:wait_for_ready, from, %{ready: true} = state) do
{:reply, :ok, state}
end
def handle_call(:wait_for_ready, from, state) do
# Don't reply yet - add to subscribers list
{:noreply, %{state | subscribers: [from | state.subscribers]}}
end
def handle_info(:became_ready, state) do
# Notify all waiting subscribers
Enum.each(state.subscribers, fn from ->
GenServer.reply(from, :ok)
end)
{:noreply, %{state | ready: true, subscribers: []}}
end
end
Benefits: