Skip to content

Instantly share code, notes, and snippets.

@James-E-A
Last active February 10, 2025 20:38
Show Gist options
  • Save James-E-A/4a7e1818dff23bce8289fa442de966df to your computer and use it in GitHub Desktop.
Save James-E-A/4a7e1818dff23bce8289fa442de966df to your computer and use it in GitHub Desktop.
Elixir actor GenServer pattern
use GenServer
def act(action, state, actor \\ nil)
def act(_, _, _) do
{:error, :badarg}
end
@impl true
def handle_call({:act, actor, action}, _from, state) do
case act(action, state, actor) do
:ok ->
# call succeeded; no specific reply; state unchanged
{:reply, :ok, state}
{:ok, new_state} ->
# call succeeded; no specific reply; state changed
{:reply, :ok, new_state, {:continue, :statechange}}
{:ok, result, :nochange} ->
# call succeeded; some specific reply; state unchanged
# LIMITATION: cannot use the atom :nochange as the state
{:reply, {:ok, result}, state}
{:ok, result, new_state} ->
# call succeeded; some specific reply; state changed
{:reply, {:ok, result}, new_state, {:continue, :statechange}}
:error ->
# call failed; no specific reply; state unchanged
{:reply, :error, state}
{:error, nil, new_state} ->
# call failed; no specific reply; state changed
# LIMITATION: cannot reply with the tuple {:error, nil}
{:reply, :error, new_state}
{:error, message} ->
# call failed; some specific reply; state unchanged
{:reply, {:error, message}, state}
{:error, message, new_state} ->
# call failed; some specific reply; state changed
{:reply, {:error, message}, new_state, {:continue, :statechange}}
end
end
@impl true
def handle_continue(message = :statechange, %{_meta: %{pubsub: pubsub_info}} = state) do
{pubsub, topic} = pubsub_info
Phoenix.PubSub.broadcast!(pubsub, topic, message)
{:noreply, state}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment