2016-09-18 20 views
0

我有這樣的代碼,其是一個基本的OTP服務器:基本藥劑OTP服務器的行爲奇怪

defmodule Clients do 
use Application 
require Logger 


def stuff do 
    Logger.debug "Clients.start/0" 
    # {:ok, pid} = Task.Supervisor.start_child(Clients.TaskSupervisor, fn -> doclient end) 
end 

def doclient(port) do 
    Logger.debug "Clients.doclient/0" 

    {:ok, socket} = :gen_tcp.listen(port,[:binary, packet: :line, active: false, reuseaddr: true]) 

#if this is under 2000ms there the process exits with a shutdown error 
    :timer.sleep(1500) 

end 

def start(_type, _args) do 
    import Supervisor.Spec 
    Logger.debug "Clients.init/1" 

    children = [ 
     supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]), 
     worker(Task, [Clients, :doclient, [4040]]) 
    ] 
    opts = [strategy: :one_for_one, name: Clients.Supervisor] 
    Supervisor.start_link(children, opts) 
end 

end 

從IEX的輸出是:

iex(1)> Clients.start(1,2) 

20:07:19.879 [debug] Clients.init/1 

20:07:19.889 [debug] Clients.doclient/0 
{:ok, #PID<0.141.0>} 
iex(2)> 
20:07:21.402 [debug] Clients.doclient/0 

20:07:22.909 [debug] Clients.doclient/0 

20:07:24.413 [debug] Clients.doclient/0 
** (EXIT from #PID<0.139.0>) shutdown 

如果doclient/1計時器呼叫正在2上述關機發生幾秒鐘,但否則會快速消失。我不知道爲什麼?如果我想讓doclient/1執行一些不到2秒的任意代碼(這不是我想象的可靠時期),這個調用總是會爆炸的。

回答

1

您正在使用Task作爲您的工作人員。所以會發生的是,一旦任務從睡眠中醒來,它完成了它的工作,並且這個過程消失了。在你的上司規格您請求:

children = [ 
    supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]), 
    worker(Task, [Clients, :doclient, [4040]]) 
] 
opts = [strategy: :one_for_one, name: Clients.Supervisor] 
Supervisor.start_link(children, opts) 

告訴OTP重新啓動你的工人,如果它完成或消失以任何方式。所以1.5秒後(你的時間睡覺),主管開始另一項任務。它在5秒內完成3次。

Supervisor.start_link具有指定重啓強度的默認選項。你可以在這裏找到文檔:

http://elixir-lang.org/docs/stable/elixir/Supervisor.Spec.html#supervise/2

默認值在5秒內最多3個重新啓動。這就是爲什麼你的主管關閉和1.5秒的睡眠時間,並愉快地繼續與2秒的間隔。

總而言之,我認爲你需要重新考慮在這個監督樹中使用任務。因爲你沒有提到它是什麼,所以不可能猜出什麼最適合你的用例。

HTH

+0

所以,任務是一次性的一次性瞬變,開始和消失。所以如果t <2s,沒有重啓的過程,並且管理員因關機而死亡?這很有道理 - 從Erlang我知道它一定是監督員重啓的問題。謝謝 – DavidH

+0

這不是問題。這正是你要求主管做的事情。 此外,任務通常是一筆交易。只要你喜歡,你可以製作它們。例如,如果您在以後調用doclient(port):timer.sleep(),任務將永遠持續。監督員不會重新啓動它。 – ash