GenServer `handle_continue` 回调可以直接从另一个进程调用吗?

jak*_*bfp 2 erlang elixir gen-server

可以通过从同一 内的另一个回调返回来调用handle_continuea 的回调。GenServer{:noreply, state, {:continue, :foo}GenServer

如果回调后我有一小部分单独的步骤GenServer.init

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 
Run Code Online (Sandbox Code Playgroud)

如果包含键,则按此顺序调用和handle_continue(:foo, state)回调。如果不是,则永远不会调用回调。handle_continue(:bar, state)argsbarhandle_continue(:bar, state)

如果我已经开始,MyGenServer例如作为监督树的一部分:

...
children = [
  ...
  {MyGenServer, %{foo: "foo"}},
  ...
]
Supervisor.start_link(children, ...)
Run Code Online (Sandbox Code Playgroud)

是否可以MyGenServer.handle_continue(:bar, state)从监督树中的另一个进程触发回调?

这更多的是一个问题,关于是否可以handle_continue以任何其他方式调用回调,而不是在同一个 内的回调之后GenServer,并且没有找到执行 中代码的替代方法handle_continue(:bar, state)

小智 6

无法直接调用回调,但您始终可以:

def handle_cast(:invoke_the_continue, state) do 
    handle_continue(:bar, state)
end
Run Code Online (Sandbox Code Playgroud)

然后GenServer.cast(your_server, :invoke_the_continue)从服务器外部调用。