我想使用Registry
模块来注册动态创建的子进程。
所以我在我的主管树中添加了注册表:
def init([]) do
children = [
supervisor(Registry, [:unique, :my_registry]),
supervisor(MyManager, []),
# ...
]
opts = [strategy: :one_for_one, name: MySupervisor]
supervise(children, opts)
end
儿童注册的情况如下:
def start_link(%{id: id}) do
GenServer.start_link(__MODULE__, [], name: {:via, Registry, {:my_registry, id}})
end
所以,我的问题是 - 如何在我的注册表中获取所有密钥(儿童pids)。
我尝试使用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
提前感谢您的帮助!
答案 0 :(得分:1)
这有点晚了,但我自己也遇到过这个问题。似乎没有正式的方法可以做到这一点,但是挖掘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
答案 1 :(得分:0)
如果我理解正确,则需要从给定的Registry
中提取所有注册的密钥。
自Elixir 1.9.0起,可以通过Registry.select/2
实现以下目的:
Registry.select(your_registry, {{:"$1", :_, :_}, [], [:"$1"]})
这将返回所有已知键的列表。
有关此功能的更多信息,请参见Hexdocs上Registry.select/2的规范。