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)
.
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.