I have a :gen_statem implementation that I want to start via a registry like this:
defmodule Arca.PodImpl do
@moduledoc false
@behaviour :gen_statem
def start_link(opts) do
cell_ref = Keyword.get(opts, :cell_ref)
case cell_ref do
nil ->
{:error, "option 'cell_ref' is required to start the Pod"}
cell_ref ->
:gen_statem.start_link(__MODULE__, opts, name: via_registry(cell_ref))
end
end
end
defp via_registry(cell_ref) do
{:via, Registry, {Arca.Registry, {__MODULE__, cell_ref}}}
end
The first problem is that I can’t start this module under a supervision tree because :gen_statem
doesn’t implement child_spec
. So then I have to implement the child_spec
myself:
# This is not automatically implemented by the gen_statem behaviour
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]}
}
end
So I end up with a module like this:
defmodule Arca.PodImpl do
@moduledoc false
def start_link(opts) do
cell_ref = Keyword.get(opts, :cell_ref)
case cell_ref do
nil ->
{:error, "option 'cell_ref' is required to start the Pod"}
cell_ref ->
:gen_statem.start_link(__MODULE__, opts, name: via_registry(cell_ref))
end
end
# This is not automatically implemented by the gen_statem behaviour
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]}
}
end
@impl true
def lock(ref), do: :gen_statem.cast(via_registry(ref), :lock)
@impl true
def unlock(ref), do: :gen_statem.cast(via_registry(ref), :unlock)
@impl true
def get_state(ref), do: :gen_statem.call(via_registry(ref), :get_state)
defp via_registry(cell_ref) do
{:via, Registry, {Arca.Registry, {__MODULE__, cell_ref}}}
end
end
For context, this is how I define my application children:
def children(_target, _env) do
[
{Registry, keys: :unique, name: Arca.Registry},
{Arca.PodImpl, cell_ref: "A1", lights_range: 75..95},
{Arca.PodImpl, cell_ref: "A2", lights_range: 61..73},
{Arca.PodImpl, cell_ref: "A3", lights_range: 20..58}
]
end
Now, the main problem is that the PodImpl
process seems to not be registered on my registry.
So when I start my application, the PodImpl
modules seem to be linked to the main supervisor (makes sense) but when I query the Registry there are no registered processes.
So when I try to call PodImpl.get_state("A1")
it returns an error saying that there is no process with that name (the one constructed by the via_registry
private function)
I hope someone can help me understand what is going on.