複数のリモートノードのアクティビティを監視する単純なgen_serverモジュールを構築しています
リモートノードが登録されると、このモジュールはerlang:monitor_node(Node、true)でノードを監視します。これはノードごとに1回だけ登録されます(ログで確認)
gen_serverのhandle_info/2コールバックでは、{nodedown、Node}メッセージをキャッチし、erlang:monitor_node(Node、false)でノードを監視解除します。このメッセージは、リモートノードがダウンしているときに一度だけ受信することを期待しています。
モジュールをテストしていたときに、リモートノードがダウンすると、数百の{nodedown、Node}メッセージ(数は数百から数千まで変化します)がgen_serverに送信されることがわかりました。
monitor_nodeによって複数のメッセージが送信されるのはなぜですか?どうすればこの動作を防ぐことができますか?
編集:ここにソースコード(の一部)があります
register_node(#node_info{node = NodeName} = NodeInfo) ->
case mnesia:read(node_info, NodeName) of
[] ->
monitor_node(NodeName, true),
error_logger:info_msg("node ~p registered", [NodeName]);
[_OldInfo] ->
error_logger:trace_msg("info of node ~p updated", [NodeName])
end,
mnesia:write(NodeInfo).
handle_cast({register_node, #node_info{} = NodeStatus}, Timer) ->
case mnesia:transaction(fun register_node/1, [NodeStatus]) of
{aborted, Reason} ->
error_logger:warning_msg("transaction register_node failed: ~p", [Reason]);
_ ->
ok
end,
{noreply, Timer};
handle_cast({shutdown_node, #node_info{} = NodeStatus}, Timer) ->
case mnesia:dirty_delete_object(NodeStatus) of
{aborted, Reason} ->
error_logger:warning_msg("transaction shutdown_node failed: ~p", [Reason]);
_ ->
ok
end,
{noreply, Timer};
handle_cast(Message, Timer) ->
error_logger:warning_msg("~p: received unknown message ~p", [?MODULE, Message]),
{noreply, Timer}.
handle_info({nodedown, Node}, Timer) ->
monitor_node(Node, false),
error_logger:info_msg("~p: node ~p down", [?MODULE, Node]),
mnesia:transaction(fun mnesia:delete/3, [node_info, Node, write]),
{noreply, Timer};
handle_info(Message, Timer) ->
error_logger:warning_msg("~p: received unknown message ~p", [?MODULE, Message]),
{noreply, Timer}.