我想使用Registry模块来注册动态创建的子进程。所以我将注册表添加到我的主管树中:
def init([]) do
children = [
supervisor(Registry, [:unique, :my_registry]),
supervisor(MyManager, []),
# ...
]
opts = [strategy: :one_for_one, name: MySupervisor]
supervise(children, opts)
end
Run Code Online (Sandbox Code Playgroud)
孩子的注册是这样发生的:
def start_link(%{id: id}) do
GenServer.start_link(__MODULE__, [], name: {:via, Registry, {:my_registry, id}})
end
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是 – 如何在我的注册表中获取所有键(子 pid)。我尝试使用Registry.keys\2,但没有成功。
def get_registry_pid do
Supervisor.which_children(MySupervisor)
|> Enum.filter(fn {id, _, _, _} -> id == Registry end)
|> List.first
|> elem(1) # get a Regisry pid from a tuple {id, pid, type, modules}
end
Registry.keys(:my_registry, get_registry_pid()) # returns []
# but
Registry.lookup(:my_registry, id) # returns PID as expected
Run Code Online (Sandbox Code Playgroud)
在此先感谢您的帮助!
小智 3
这有点晚了,但我自己也遇到了这个问题。似乎没有官方的方法可以做到这一点,但通过挖掘Registry源代码并阅读一些内容,:erts我提出了以下解决方案:
defmodule MyApp.Sensor.Registry do
@doc """
Lists all the registered sensors from the registry.
"""
@spec list_sensors!(module) :: [{String.t(), pid, any}]
def list_sensors!(registry \\ __MODULE__) do
try do
# The args for `lookup_element` are taken from the private function
# `info/1` from the `Registry` module.
{_kind, _partitions, table, _pid_ets, _} =
:ets.lookup_element(registry, -1, 2)
# select_all is the result of `:ets.fun2ms(&(&1))` which works from iex
# but not when compiled for reasons beyond my comprehension
select_all = [{:"$1", [], [:"$1"]}]
:ets.select(table, select_all)
catch
:error, :badarg ->
raise ArgumentError, "#{inspect(registry)} is not running"
end
end
end
Run Code Online (Sandbox Code Playgroud)