erlangelixirgen-server

Can the GenServer `handle_continue` callback directly be invoked from another process?


The handle_continue callback of a GenServer can be invoked by returning {:noreply, state, {:continue, :foo} from another callback inside the same GenServer.

If I have a small cascade of separate steps after the GenServer.init callback:

defmodule MyGenServer do
  use GenServer

  def start_link(args \\ %{}) do
    GenServer.start_link(__MODULE__, args, [])
  end
  
  @impl true
  def init(args) do
    {:ok, args, {:continue, :foo}}
  end

  @impl true
  def handle_continue(:foo, state)
    case foo(state) do
      {:ok, state} ->
        {:noreply, state, {:continue, :bar}}

      {:error, :bar_not_set} ->
        {:noreply, state}
  end

  @impl true
  def handle_continue(:bar, state)
    state = bar(state)
    {:noreply, state}
  end

  defp foo(state = %{bar: _}) do
    {:ok, state}
  end
  defp foo(_state) do
    {:error, :bar_not_set}
  end

  defp bar(state) do
    # ...
    state
  end
end 

the handle_continue(:foo, state) and handle_continue(:bar, state) callbacks are invoked in this order, if the args contained a bar key. If not, the handle_continue(:bar, state) callback is never invoked.

If I have started MyGenServer e.g. as part of a supervision tree:

...
children = [
  ...
  {MyGenServer, %{foo: "foo"}},
  ...
]
Supervisor.start_link(children, ...)

would it be possible to trigger the MyGenServer.handle_continue(:bar, state) callback from another process in the supervision tree?

It is more a question, about if invoking a handle_continue callback in any other way, than after a callback inside the same GenServer, is possible at all and not to find an alternative of executing the code in handle_continue(:bar, state).


Solution

  • It is not possible to invoke the callback directly, but you can always have:

    def handle_cast(:invoke_the_continue, state) do 
        handle_continue(:bar, state)
    end
    

    and then call GenServer.cast(your_server, :invoke_the_continue) from outside your server.