6

スーパーバイザーと GenServer を可能な限りシンプルに組み合わせたプロジェクトがあります。iex から呼び出す場合:

EchoCmd.Supervisor.start_link([:Hello])
GenServer.call(:echoserver, :echo)
GenServer.call(:echoserver, :mumble)
GenServer.call(:echoserver, :echo)

:mumble 呼び出しで例外が発生し、GenServer が再起動され、2 番目の :echo 呼び出しが正常に機能します。

他の方法でコードを実行すると、Supervisor は GenServer の再起動に失敗します。たとえば、次のようにメイン モジュールを使用してプロジェクトの escript を作成します。

defmodule EchoCmd.Echo do
    def main(args) do
        EchoCmd.Supervisor.start_link([:Hello])
        GenServer.call(:echoserver, :echo)
        GenServer.call(:echoserver, :mumble)
        GenServer.call(:echoserver, :echo)
    end
end

:mumble 呼び出しで例外が発生し、Supervisor が GenServer を再起動することなく escript が終了します。

Supervisor モジュールと Server モジュールのコードは含めていません。これらは iex から呼び出されたときに正常に動作するためです。ここでは不要だと思います。

概念的な誤解がありますか? これは不可能ですか、それとも何か間違っていますか?

4

2 に答える 2

6

問題はサーバーとスーパーバイザーにあるのではなく、それらを呼び出す方法にあります。別のプロセスが への応答を待っている間にサーバーが終了するGenServer.callと、呼び出し元のプロセスも終了するため、最後の呼び出しは発生しません。この理由は、同期呼び出しが失敗した場合、プロセスが無効な状態で続行できない可能性があるためです (GenServer.call同期ではなく同期GenServer.castです)。スーパーバイザーをテストするためだけにこれを行っている場合は、次を試すことができます。

defmodule EchoCmd.Echo do
    def main(args) do
        EchoCmd.Supervisor.start_link([:Hello])
        GenServer.cast(:echoserver, :echo)
        GenServer.cast(:echoserver, :mumble)
        GenServer.cast(:echoserver, :echo)
    end
end

それが機能する理由iexは、出口をiexトラップし、別の行を入力できるようにするためです。

于 2014-11-17T09:00:23.017 に答える