2016-08-31 10 views
0

を開始db。エリクサースーパーバイザ-init-動的に私のようなシンプルなスーパーバイザモジュールが持っている子供たちに

私はINITで...)(Process.send_afterを試みたが、それはエラーになります(**(EXIT)プロセス自体を呼び出そうとしました)

それもこのモジュールでこれを実行しようとする意味がありますか?別のワーカー(genserver)をセットアップしてDBにクエリを行い、このUsers.Supervisor.create_user/1を呼び出す必要がありますか?例:この関数は、新たに開始したスーパーバイザプロセスに子供の仕様を返すよう

defmodule Final.Users.Starter do 
    alias Final.Repo 
    alias Final.Users.Supervisor, as: Sup 
    import Ecto.Query, only: [from: 2] 
    use GenServer 

    def start_link() do 
    GenServer.start_link(__MODULE__, :ok, name: __MODULE__) 
    end 

    def init(:ok) do 
    Process.send_after(self(), :started, 0) 
    {:ok, %{}} 
    end 

    def handle_info(:started, %{}) do 
    query = from(p in "users", 
      select: p.id) 
    ids = Final.Repo.all(query) 
    Enum.each(ids, fn(x) -> Sup.create_user(x) end) 

    {:noreply, %{}} 
    end 
end 
+0

"私はinitでProcess.send_after()を試しましたが、エラー(**(EXIT)プロセスが自分自身を呼び出そうとしました)" init/1'の 'Process.send_after/3'がうまく動作します'GenServer'(私はあなたの' Final.Users.Starter'をコピーし、Ectoとスーパーバイザ関連のものを削除しました)。そのエラーが発生したスタックトレースを投稿できますか?このエラーは、プロセスが 'GenServer.call'を自分自身に送信しようとしたときにだけスローされます(デッドロックが発生します)。 – Dogbert

答えて

1

あなたは上司のinit/1コールバックでダイナミックな子供を開始することはできません。言い換えれば、スーパーバイザーはこのコールバックが返される前に子供を始める方法を知らない。

初期化作業を行うためだけにGenServerをセットアップするのはあまりにも多いようです。よりよい考えは、一時的なプロセスを生成して、そのジョブと終了を直ちに実行することです。この目的のために

あなたはTaskを使用することができます。

Task.start_link(fn -> 
        query = from(p in "users", select: p.id) 
        ids = Final.Repo.all(query) 
        Enum.each(ids, fn(x) -> Sup.create_user(x) end) 
       end) 

このようなタスクは、アプリケーションのメインモジュールから出現することができます。ただし、このタスクが失敗すると、終了信号が発信者に返送されます。

関連する問題