1

target_interceptor登録および登録解除メッセージを受信すると、 の下でワーカーを開始または終了する単純なアプリケーションがありますsimple_one_for_one rpc_server_supervisor

スーパーバイザーのコードrpc_server_supervisor:

init([]) ->
    MaxRestart = 5,
    MaxTime = 3600,
    {ok, {{simple_one_for_one, MaxRestart, MaxTime},
            [{rbmq_rpc_server, 
                {rbmq_rpc_server, start_link, []},
                temporary,
                10000,
                worker,
                [rbmq_rpc_server]}]}}.

の登録メッセージtarget_interceptor:

handle_cast({register, Args}, S = #state{channel = Channel, supervisor=Sup, refs=R, qs_link = QSLinks}) ->
    {Connection, QueueName, Node} = Args,   
    {Ok, Pid} = supervisor:start_child(Sup, [Connection, QueueName, Node]),
    Ref = erlang:monitor(process, Pid),
{noreply, S#state{refs=gb_sets:add(Ref,R), qs_link=orddict:append(binary_to_list(QueueName),Pid,QSLinks)}};

のメッセージを登録解除target_interceptor:

handle_cast({unregister,{QueueName}}, S = #state{supervisor = Sup, qs_link = QSLinks}) ->
    Pid = orddict:fetch(QueueName,QSLinks) 
    case supervisor:terminate_child(Sup,Pid) of
         ok -> Success = true;
         Error -> io:format("Error ~p~n",[Error]),
                  Success = false
    end,
{noreply, S#state{qs_link=orddict:erase(QueueName,QSLinks)}}

Erlang の私のバージョンは: R15B01

最初の問題は、タプル {OK, Pid} = {error, <0.57.0>}; の登録アクションを処理するときです。何か問題が発生したことを示していますが、Pid 57 の gen_server rbmq_rpc_server は正しく機能しており、メッセージに応答しています。start_child 関数の戻り値がエラーになるのはなぜですか? 何が悪かったのか?

2 番目の問題は、登録解除アクションを処理するときです。ここで、ChildID ではなく Pid を参照しているにもかかわらず、supervisor:terminate_child(Sup,Pid) が {error,simple_one_for_one) を返します。なぜこのように動作し、スーパーバイザーの子を動的かつ個別に終了するにはどうすればよいですか?

編集:target_interceptorとの両方rpc_server_supervisorがスーパーバイザーによってrbmq_sup_sup監督されています:

init({Nodeid, Node}) ->
    MaxRestart = 1,
    MaxTime = 3600,
    {ok, {{rest_for_one, MaxRestart, MaxTime},
            [{server,
                {target_interceptor, start_link, [target, self(), {Nodeid, Node}]},
                permanent,
                5000,
                worker,
                [target_interceptor]}]}}.

編集: rpc_server_supervisor は target_interceptor init() 関数で呼び出されます (ここでの Sup は rbmq_sup_sup スーパーバイザーです):

handle_info({start_worker_supervisor, Sup}, S = #state{}) ->
    {ok, Pid} = supervisor:start_child(Sup, ?SPEC),
    link(Pid),
    {noreply, S#state{sup=Pid}};

-define(SPEC,
        {rpc_server_sup,
            {rpc_server_sup, start_link, []},
            temporary,
            10000,
            supervisor,
            [rpc_server_sup]}).
4

1 に答える 1