Я изучаю эликсир всего несколько недель и хочу создать подходящее приложение с его модулем приложения, супервизором и (на данный момент только одним) работником.
Дни изучения руководств, документации, форума Elixir и stackoverflow привели меня к такому пониманию:
- Мне нужен модуль с
use Application
- Мне не нужен отдельный модуль для супервизора, для простого приложения достаточно вызова
Supervisor.start_link/2
и сохранения возвращенного pid. - модуль приложения имеет функцию
start/2
, которая возвращает{:ok, pid}
(которое является возвращаемым значением последнего вызова в нем,Supervisor.start_link(worker_module, options)
) - Мне нужен рабочий модуль, который определяет
child_spec/2
,init/1
иstart_link/1
Supervisor.start_link/2
вызываетinit/1
, а затемstart_link/1
рабочего с заданными параметрамиinit/1
возвращает определенное значение
Теперь у меня проблема с последней частью. Согласно полученной мной ошибке, функция init
моего рабочего возвращает "неверное значение", но я не могу понять, каким должно быть возвращаемое значение, чтобы supervisor.start_link/2
не завершился ошибкой.
Значения, которые я уже пробовал, когда init определен как init(opts)
:
- ноль
- {: хорошо, сам ()}
- {: хорошо, __MODULE__}
- {: ok, opts}
- Task.start_link (fn () -> function_that_actually_does_the_work () конец)
- :нормальный
Это сообщение об ошибке, которое я получаю от регистратора после строки {:ok, pid} = Supervisor.start_link(MyAppMain.Worker, [])
:
** (Mix) Could not start application myapp: exited in: MyAppMain.start(:normal, [])
** (EXIT) an exception was raised:
** (MatchError) no match of right hand side value: {:error, {:bad_return, {MyAppMain.Worker, :init, {:ok, %{}}}}}
lib/MyAppMain.ex:15: MyAppMain.start/2
(kernel) application_master.erl:273: :application_master.start_it_old/4
Итак, какие возвращаемые значения принимает Supervisor.start_link/2
?
РЕДАКТИРОВАТЬ: какой-то фактический код
Модуль приложения:
defmodule MyAppMain do
use Application
def start(_type, _args) do
{:ok, pid} = Supervisor.start_link(MyAppMain.Worker, [])
end
end
Рабочий модуль:
defmodule MyAppMain.Worker do
def child_spec(opts) do
%{
id: MyAppMain.Worker,
start: {__MODULE__, :start_link, []},
restart: :transient,
type: :worker
}
end
def start_link(state) do
do_work() # returns a "fn() -> nil end", because "expected a function"
end
def init(opts) do
{:ok, %{}} # Also tried putting the elements of the above list here.
end
defp do_work()
#do some work
if(prompt_restart()) do
do_work()
else
fn() -> nil end
end
end
defp prompt_restart() do
# prompt the user whether to repeat the task via IO.gets, return either true or false
end
end