Erlang/OTPでGen_Eventハンドラーの切り替え中にイベントが処理されるようにする

StackOverflow https://stackoverflow.com/questions/3767902

  •  04-10-2019
  •  | 
  •  

質問

いくつかのバージョンがあるとしましょう gen_event ハンドラーとプログラムが実行されている間にそれらを変更したい:

-module(logger_all).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
    {ok, []}.
handle_event({Severity, ErrorMsg}, State) ->
    io:format("***~p*** ~p~n", [Severity, ErrorMsg]),
    {ok, State}.
terminate(_Args, _State) ->
    ok.

-module(logger_errors_only).
-behaviour(gen_event).
-export([init/1, handle_event/2, terminate/2]).
init(_Args) ->
    {ok, []}.
handle_event({error, ErrorMsg}, State) ->
    io:format("***Error*** ~p~n", [ErrorMsg]),
    {ok, State}.
handle_event({_, ErrorMsg}, State) ->
    {ok, State}. %% ignore everything except errors
terminate(_Args, _State) ->
    ok.

明らかに、1つのハンドラーを削除してもう1つを追加することで、それらを切り替えることができます。

log_errors_only() -> 
    gen_event:delete_handler(error_man, logger_all, []),
    gen_event:add_handler(error_man, logger_errors_only, []).

しかし、これは人種の状態の可能性を残します。もしも error_man 間違った時間にイベントを受け取ると、記録されません。または、アクションの順序を変更すると、2回記録されますが、これも望ましくありません。一度正確に処理されることを確認するにはどうすればよいですか?

この場合、私は1つのハンドラーを持って、ロギングレベルを保持することができます。 State, 、しかし、これが受け入れられないと仮定します。

役に立ちましたか?

解決

OTPチームは、このようなニーズを予見するのが得意です。 gen_eventには関数があります イベントハンドラーを交換します 原子的:

log_errors_only() ->
    gen_event:swap_handler(error_man,
                           {logger_all, swapped_out},
                           {logger_errors_only, []}).
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top