Я пытаюсь разрешить GenServer, управляемый Приложением, по зарегистрированному имени в elixir 1.9. Вот пример кода:
defmodule Experiment do
use Application
def start(_type, _args) do
child_specs = [
config_spec()
]
Supervisor.start_link(child_specs, name: Experiment, strategy: :one_for_one)
end
defp config_spec() do
%{
id: Experiment.Data,
start: {
Experiment.Data,
:start_link,
[
"some data",
# set name of child process here
[:name, Experiment.Data]
]
}
}
end
end
defmodule Experiment.Data do
use GenServer
require Logger
def start_link(data, options \\ []) do
Logger.info("starting with data '#{data}' and options [#{Enum.join(options, ", ")}]")
GenServer.start_link(__MODULE__, data, options)
end
@impl true
def init(data) do
Logger.info("starting")
{:ok, data}
end
@impl true
def handle_call(:data, _from, state) do
{:reply, state, state}
end
@impl true
def terminate(reason, _state) do
Logger.info("terminated: #{reason}")
end
def get_data(server) do
GenServer.call(server, :data)
end
end
Я проверял это в iex (iex -S mix
):
iex(1)> {:ok, sup_pid} = Experiment.start(nil, nil)
10:45:36.914 [info] starting with data 'some data' and options [name, Elixir.Experiment.Data]
10:45:36.916 [info] starting
{:ok, #PID<0.189.0>}
iex(2)> Experiment.Data.get_data(Experiment.Data)
** (exit) exited in: GenServer.call(Experiment.Data, :data, 5000)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(elixir) lib/gen_server.ex:979: GenServer.call/3
iex(2)> Experiment.Data.get_data(Elixir.Experiment.Data)
** (exit) exited in: GenServer.call(Experiment.Data, :data, 5000)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(elixir) lib/gen_server.ex:979: GenServer.call/3
iex(2)> send(Experiment.Data, {self(), "hi"})
** (ArgumentError) argument error
:erlang.send(Experiment.Data, {#PID<0.187.0>, "hi"})
iex(2)> send(Experiment, {self(), "hi"})
{#PID<0.187.0>, "hi"}
iex(3)>
10:46:05.410 [error] Supervisor received unexpected message: {#PID<0.187.0>, "hi"}
Что меня смущает, так это то, что я пытался зарегистрировать Experiment.Data
с именем Experiment.Data
. Но когда я пытаюсь отправить сообщение процессу с именем Experiment.Data
, оно не может быть найдено. Я добавил хук terminate
, чтобы проверить, что он не умирает рано, но это, похоже, не вызывается. Я добавил строки регистрации, которые показывают мне, что процесс запускается. Я также попытался назвать приложение по зарегистрированному имени, которое работает. Однако называть его потомком (Experiment.Data
) по имени нельзя. Я понимаю способ запуска дочерних процессов , похоже, недавно изменился , что, похоже, вызвало некоторую путаницу. Что я делаю не так?
EDIT
Изменение функции config_spec на это, похоже, позволило ей работать:
defp config_spec() do
%{
id: Experiment.Data,
start: {
Experiment.Data,
:start_link,
[
"some data",
[
{:name, Experiment.Data}
]
]
}
}
end