Elixir GenServer.start_link выдает исключение вместо возврата кортежа

Я немного играю с GenServer и у меня есть проблемы с реализацией пользовательских init Перезвоните.

Пожалуйста, рассмотрите следующий код:

defmodule GenS do
  use GenServer

  def start_link(initial \\ 0) do
    GenServer.start_link(__MODULE__, initial)
  end

  def init(initial) do
    case initial do
      3 -> {:stop, "Can't initialise with 3"}
      _ -> {:ok, initial}
    end
  end
end

case GenS.start_link(3) do
  {:error, reason} -> IO.puts "Failed with #{reason}"
  {:ok,    _}      -> IO.puts "This has worked!"
end

IO.puts "I'm still alive!"

При выполнении этого кода я вижу вывод:

▶ elixir gens.ex
** (EXIT from #PID<0.46.0>) "Can't initialise with 3"

В то время как я ожидал аналогичный вывод для успешной ветви (когда значение отличается от 3 в качестве аргумента)

▶ elixir gens.ex
This has worked!
I'm still alive!

Согласно документации GenServer.start_link/3:

Если init/1 обратный вызов завершается неудачно с причиной, эта функция возвращает {:error, reason}, В противном случае, если он вернется {:stop, reason} или же :ignore, процесс завершается и эта функция возвращает {:error, reason} или же :ignore соответственно.

Я ожидаю, что кортеж будет возвращен, что я мог бы скорректировать, но, похоже, это не так. Есть ли у вас какие-либо рекомендации?

1 ответ

Решение

Я ожидаю, что кортеж будет возвращен, что я мог бы скорректировать, но, похоже, это не так. Есть ли у вас какие-либо рекомендации?

Проблема здесь в том, что вы связываете с порожденным процессом и возвращаете {:stop, ...} от init отправляет сигнал на выход вызывающему процессу, который по умолчанию убивает вызывающий процесс.

Вы можете либо перейти на использование GenServer.start (и вручную связать процессы позже, если хотите), или перехватить сигналы выхода, выполнив следующее перед запуском GenS:

Process.flag(:trap_exit, true)

(Обратите внимание, что это отправит сообщение вызывающему процессу, когда GenSумирает, от которого вы можете отказаться, чтобы предотвратить потерю памяти.)

В обоих случаях я получаю следующий вывод:

Failed with Can't initialise with 3
I'm still alive!
Другие вопросы по тегам