Невозможно запустить супервизор: (Protocol.UndefinedError) протокол Enumerable не реализован для

Я пытаюсь запустить Supervisor и GenServer:

defmodule SubscriptionManagerSupervisor do
  use Supervisor

  def start_link do
    Supervisor.start_link(__MODULE__, [], [{:name, __MODULE__}])
  end

  # supervisor callback
  def init([]) do
    interval = 1000
    children = worker(SubscriptionManagerServer, [interval])
    supervise(children, strategy: :one_for_one)
  end
end

И мой GenServer:

defmodule SubscriptionManagerServer do
  use GenServer
  import Logger

  def start_link(interval) do
    GenServer.start_link(__MODULE__, [interval])
  end

  def init(interval) do
    state = :calendar.universal_time()
    Logger.info "SubscriptionManagerServer init(). State: #{state} interval: #{interval}"
    # This will send message to self on the interval. handle_info handles it.
    :timer.send_interval(interval)
    {:ok, state}
  end

  def handle_info(url, state) do
    new_state = :calendar.universal_time()
    Logger.info "SubscriptionManager handle_info(). new_state: #{new_state}"
    {:noreply, new_state}
  end
end

Я пытаюсь запустить все:

defmodule SubscriptionManagerApp do
  use Application
  import Logger

  def start(_type, _args) do
    Logger.info "Starting the SubscriptionManager."
    SubscriptionManagerSupervisor.start_link()
  end
end

Однако я получаю следующую ошибку:

** (Mix) Could not start application subscription_manager: SubscriptionManagerApp.start(:normal, []) returned an error: an exception was raised:
    ** c for {SubscriptionManagerServer, {SubscriptionManagerServer, :start_link, [1000]}, :permanent, 5000, :worker, [SubscriptionManagerServer]}
        (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
        (elixir) lib/enum.ex:116: Enumerable.reduce/3
        (elixir) lib/enum.ex:1636: Enum.reduce/3
        (elixir) lib/enum.ex:1188: Enum.map/2
        (elixir) lib/supervisor/spec.ex:169: Supervisor.Spec.supervise/2
        (stdlib) supervisor.erl:294: :supervisor.init/1
        (stdlib) gen_server.erl:328: :gen_server.init_it/6
        (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3

Я попытался изменить некоторые аргументы и внимательно просмотрел документы, но я в тупике.


person sheldonkreger    schedule 07.09.2016    source источник
comment
ваш GenServer.start_link с interval не с [interval]. Попробуйте заменить его   -  person TheAnh    schedule 07.09.2016


Ответы (1)


В коде есть несколько проблем:

  1. children должен быть списком.
  2. Второй аргумент GenServer.start_link должен быть просто interval, а не [interval].
  3. Вам нужно состояние inspect(), прежде чем вводить его в интерполяцию строк, поскольку это кортеж.
  4. :timer.send_interval/1 нет, только /2 и /3.

Окончательные изменения:

@@ -8,7 +8,7 @@ defmodule SubscriptionManagerSupervisor do
   # supervisor callback
   def init([]) do
     interval = 1000
-    children = worker(SubscriptionManagerServer, [interval])
+    children = [worker(SubscriptionManagerServer, [interval])]
     supervise(children, strategy: :one_for_one)
   end
 end
@@ -18,20 +18,20 @@ defmodule SubscriptionManagerServer do
   import Logger

   def start_link(interval) do
-    GenServer.start_link(__MODULE__, [interval])
+    GenServer.start_link(__MODULE__, interval)
   end

   def init(interval) do
     state = :calendar.universal_time()
-    Logger.info "SubscriptionManagerServer init(). State: #{state} interval: #{interval}"
+    Logger.info "SubscriptionManagerServer init(). State: #{inspect(state)} interval: #{interval}"
     # This will send message to self on the interval. handle_info handles it.
-    :timer.send_interval(interval)
+    :timer.send_interval(interval, :tick)
     {:ok, state}
   end

   def handle_info(url, state) do
     new_state = :calendar.universal_time()
-    Logger.info "SubscriptionManager handle_info(). new_state: #{new_state}"
+    Logger.info "SubscriptionManager handle_info(). new_state: #{inspect(new_state)}"
     {:noreply, new_state}
   end
 end

Демо:

$ mix run --no-halt

16:08:17.771 [info]  Starting the SubscriptionManager.

16:08:17.776 [info]  SubscriptionManagerServer init(). State: {{2016, 9, 7}, {10, 38, 17}} interval: 1000

16:08:18.780 [info]  SubscriptionManager handle_info(). new_state: {{2016, 9, 7}, {10, 38, 18}}

16:08:19.780 [info]  SubscriptionManager handle_info(). new_state: {{2016, 9, 7}, {10, 38, 19}}

16:08:20.784 [info]  SubscriptionManager handle_info(). new_state: {{2016, 9, 7}, {10, 38, 20}}

16:08:21.784 [info]  SubscriptionManager handle_info(). new_state: {{2016, 9, 7}, {10, 38, 21}}

16:08:22.782 [info]  SubscriptionManager handle_info(). new_state: {{2016, 9, 7}, {10, 38, 22}}

^C
person Dogbert    schedule 07.09.2016
comment
Что касается супервайзера, я чувствовал, что перепробовал все. Однако я не понимал, что дети должны быть списком. Это было ключом. Спасибо! - person sheldonkreger; 08.09.2016