How to get keys of registered children (via Register)

Hello.
I want to use Registry module to register dynamically created children processes.
So I added registry into my supervisor tree:

def init([]) do
    children = [
      supervisor(Registry, [:unique, :my_registry]),
      supervisor(MyManager, []),
      ...
    ]
    opts = [strategy: :one_for_one, name: MySupervisor]
    supervise(children, opts)
  end

Registration of children happens like this:

  def start_link(%{id: id}) do
    GenServer.start_link(__MODULE__, [], name: {:via, Registry, {:my_registry, id}})
  end

So, my questions is – how to get all keys (children pids) in my Registry.
I tried to use Registry.keys\2, but without success.

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

Thanks in advance for any help!

3 Likes

Second argument passed to Registry.keys/2 is a pid of a process which put an entry into registry (i.e. the one which called Registry.register/3 which is done behind the scenes when using :via option). I think that in your case it is a pid of MySupervisor because this is the process which called start_link/1 of your workers.

Try it with supervisor’s pid and let us know if that worked! :slight_smile:

1 Like

Thank for the answer @arkgil!
In the end I figured out how Registry works. It links a key/value to a process which used to register it. So in my case each id is linked to a process (on starting procedure using :via) and when this process dies, the key automatically deletes from Registry (because linked to it).
Answer is – it’s impossible to iterate through these ids in Registry, but it’s possible to use Supervisor.which_children and get all children pids instead :slight_smile:
I also use Registry to store an additional data for processes (using processes itself to register data), and it automatically cleans when a process killed.

5 Likes

Looks like you have it figured out, but I have a sample project here - https://github.com/amokan/registry_sample

In particular, you can look at how I used the Supervisor.which_children to get the registry keys here - https://github.com/amokan/registry_sample/blob/master/lib/registry_sample/account_supervisor.ex#L93

3 Likes

I have to say, I was initially a bit perplexed by Registry.keys/2. I think I misunderstood its functionality based on some incorrect, preconceived notions.

I discovered this thread when trying to figure out my use case, so I figured I’d add a post in case it’s useful to someone in future.

I just wanted to get a list of all registered keys in a registry and assumed (without reading the docs to be fair) that Registry.keys/2 would do that, in much the same way that Registry.count/1 returns a count of all items in a registry.

I read through the docs a bit and realised that Registry.select/2 does this; i.e:

# get a list of keys
Registry.select(MyRegistry, [{{:"$1", :_, :_}, [], [:"$1"]}])

# get a list of two-element key/pid tuples
Registry.select(MyRegistry, [{{:"$1", :"$2", :_}, [], [{{:"$1", :"$2"}}]}])
4 Likes