elixir - Elixir 的 GenServer 的 handle_call、handle_info、handle_cast 未被调用
问题描述
我已经实现了一个简单的Application
->DynamicSupervisor
系统,它在启动时Application
创建一个DynamicSupervisor
,然后向它发送一条消息以开始一些工作。问题是没有任何消息(通过 GenServer's cast
, Kernel's send
)实际上被捕获。试图GenServer.call()
抛出以下错误
DynamicSupervisor.handle_call/3 中没有匹配的函数子句
这很奇怪,因为我已经实现了它(按照那个规范)。我确定该DynamicSupervisor
模块已启动并且不会在启动时退出。
应用模块代码:
defmodule Simulacra.Application do
use Application
def start(_type, _args) do
children = [
Simulacra.MainSupervisor
]
opts = [strategy: :one_for_one, name: Simulacra.Supervisor]
{:ok, pid} = Supervisor.start_link(children, opts)
start_supervisors(Supervisor.which_children(pid))
{:ok, pid}
end
defp start_supervisors([h|_t] = list) when is_list(list) do
{_, pid, _, _} = h
start_supervisors(pid)
end
defp start_supervisors([]) do
#noop
IO.puts "Something"
end
defp start_supervisors(pid) do
GenServer.cast(pid, :start)
send(pid, :ping)
GenServer.call(pid, :ping) <-- Throws an error
end
end
主管代码:
defmodule Simulacra.MainSupervisor do
@moduledoc false
use DynamicSupervisor
def start_link([]) do
DynamicSupervisor.start_link(__MODULE__, [], name: __MODULE__)
end
def init(_noop) do
DynamicSupervisor.init(strategy: :one_for_one)
end
def handle_info(:ping, state) do
IO.puts "sth"
end
def handle_cast(:start, state) do
# do_something
{:noreply, state}
end
def handle_call(:ping, _from, _x) do
{:reply, "bing", "bong"}
end
解决方案
DynamicSupervisor
是行为的自定义实现。GenServer
它唯一可覆盖的功能是child_spec/1
.
你casts
虽然被有效地忽略了。当您投射消息或发送信息时,当进程无法处理它(或者即使它不存在)时,VM 会简单地忽略它。call/3
是同步的,因此发送者期望回复,这就是您看到它引发的原因.
试试看GenServer.cast pid, :foo
,你会收到:ok
回信,因为这些消息是不承诺送达的。
推荐阅读
- python - 通过减去两个值对熊猫数据框进行排序
- python - 将每个文本节点映射到 Python 中的匿名函数
- sql - 在 SQL Server 中添加日期
- reactjs - 谷歌地图 api 的问题和打字稿的反应
- flutter - 我已经有这个问题已经有一个星期了,但要知道有没有用,每当我点击颤动运行时,我都会收到这个错误
- sql - 没有聚合函数的动态 TSQL Pivot
- google-cloud-platform - ClickToDeply Image 没有安装 PHPMyAdmin
- typescript - 条件类型:使用接口键及其类型作为函数的参数
- javascript - 为什么动态创建的按钮在点击时不会被删除?
- selenium - 我们如何根据开发场景修复自动运行特定的测试用例?硒+java+黄瓜