|
49 | 49 | overview/1,
|
50 | 50 | import_state/2,
|
51 | 51 | check_conf_change/1,
|
52 |
| - list_nodes/1]). |
| 52 | + list_nodes/1, |
| 53 | + state_enter/2 |
| 54 | + ]). |
53 | 55 | -export([make_purge_nodes/1,
|
54 | 56 | make_update_conf/1]).
|
55 | 57 |
|
@@ -629,17 +631,20 @@ ensure_monitors(#command_register_consumer{vhost = VirtualHost,
|
629 | 631 | Monitors0,
|
630 | 632 | Effects) ->
|
631 | 633 | GroupId = {VirtualHost, Stream, ConsumerName},
|
| 634 | + %% get the group IDs that depend on the PID |
632 | 635 | Groups0 = maps:get(Pid, PidsGroups0, #{}),
|
633 |
| - PidsGroups1 = |
634 |
| - maps:put(Pid, maps:put(GroupId, true, Groups0), PidsGroups0), |
| 636 | + %% add the group ID |
| 637 | + Groups1 = Groups0#{GroupId => true}, |
| 638 | + %% update the PID-to-group map |
| 639 | + PidsGroups1 = PidsGroups0#{Pid => Groups1}, |
635 | 640 | {State0#?MODULE{pids_groups = PidsGroups1}, Monitors0#{Pid => sac},
|
636 | 641 | [{monitor, process, Pid}, {monitor, node, node(Pid)} | Effects]};
|
637 | 642 | ensure_monitors(#command_unregister_consumer{vhost = VirtualHost,
|
638 | 643 | stream = Stream,
|
639 | 644 | consumer_name = ConsumerName,
|
640 | 645 | connection_pid = Pid},
|
641 |
| - #?MODULE{groups = StreamGroups0, pids_groups = PidsGroups0} = |
642 |
| - State0, |
| 646 | + #?MODULE{groups = StreamGroups0, |
| 647 | + pids_groups = PidsGroups0} = State0, |
643 | 648 | Monitors,
|
644 | 649 | Effects)
|
645 | 650 | when is_map_key(Pid, PidsGroups0) ->
|
@@ -671,8 +676,7 @@ ensure_monitors(#command_unregister_consumer{vhost = VirtualHost,
|
671 | 676 | maps:remove(Pid, Monitors), [{demonitor, process, Pid} | Effects]};
|
672 | 677 | false ->
|
673 | 678 | %% one or more groups still depend on the PID
|
674 |
| - {State0#?MODULE{pids_groups = |
675 |
| - maps:put(Pid, PidGroup1, PidsGroups0)}, |
| 679 | + {State0#?MODULE{pids_groups = PidsGroups0#{Pid => PidGroup1}}, |
676 | 680 | Monitors, Effects}
|
677 | 681 | end;
|
678 | 682 | ensure_monitors(#command_connection_reconnected{pid = Pid},
|
@@ -735,8 +739,7 @@ handle_connection_node_disconnected(ConnPid,
|
735 | 739 | ConnPid, Acc, G)
|
736 | 740 | end, State1, Groups),
|
737 | 741 | T = disconnected_timeout(State2),
|
738 |
| - {State2, [{timer, {sac, node_disconnected, |
739 |
| - #{connection_pid => ConnPid}}, T}]} |
| 742 | + {State2, [node_disconnected_timer_effect(ConnPid, T)]} |
740 | 743 | end.
|
741 | 744 |
|
742 | 745 | -spec handle_node_reconnected(node(), state(), ra_machine:effects()) ->
|
@@ -885,6 +888,44 @@ list_nodes(#?MODULE{groups = Groups}) ->
|
885 | 888 | end, #{}, Groups),
|
886 | 889 | maps:keys(Nodes).
|
887 | 890 |
|
| 891 | +-spec state_enter(ra_server:ra_state(), state() | term()) -> |
| 892 | + ra_machine:effects(). |
| 893 | +state_enter(leader, #?MODULE{groups = Groups} = State) |
| 894 | + when is_record(State, ?MODULE)-> |
| 895 | + %% iterate over groups |
| 896 | + {Nodes, DisConns} = |
| 897 | + maps:fold(fun(_, #group{consumers = Cs}, Acc) -> |
| 898 | + %% iterage over group consumers |
| 899 | + lists:foldl(fun(#consumer{pid = P, |
| 900 | + status = {?DISCONNECTED, _}, |
| 901 | + ts = Ts}, |
| 902 | + {Nodes, DisConns}) -> |
| 903 | + %% disconnected consumer, |
| 904 | + %% store connection PID and node |
| 905 | + {Nodes#{node(P) => true}, |
| 906 | + DisConns#{P => Ts}}; |
| 907 | + (#consumer{pid = P}, {Nodes, DisConns}) -> |
| 908 | + %% store connection node |
| 909 | + {Nodes#{node(P) => true}, DisConns} |
| 910 | + end, Acc, Cs) |
| 911 | + end, {#{}, #{}}, Groups), |
| 912 | + DisTimeout = disconnected_timeout(State), |
| 913 | + %% monitor involved nodes |
| 914 | + %% reset a timer for disconnected connections |
| 915 | + [{monitor, node, N} || N <- maps:keys(Nodes)] ++ |
| 916 | + [begin |
| 917 | + Time = case ts() - Ts of |
| 918 | + T when T < 10_000 -> |
| 919 | + %% 10 seconds is arbitrary, nothing specific about the value |
| 920 | + 10_000; |
| 921 | + T when T > DisTimeout -> |
| 922 | + DisTimeout |
| 923 | + end, |
| 924 | + node_disconnected_timer_effect(P, Time) |
| 925 | + end || P := Ts <- DisConns]; |
| 926 | +state_enter(_, _) -> |
| 927 | + []. |
| 928 | + |
888 | 929 | nodes_from_group(#group{consumers = Cs}) when is_list(Cs) ->
|
889 | 930 | lists:foldl(fun(#consumer{pid = Pid}, Acc) ->
|
890 | 931 | Acc#{node(Pid) => true}
|
@@ -1295,6 +1336,10 @@ csr(Pid, Id, Owner, Status) ->
|
1295 | 1336 | csr_status(C, Status) ->
|
1296 | 1337 | C#consumer{status = Status, ts = ts()}.
|
1297 | 1338 |
|
| 1339 | +node_disconnected_timer_effect(Pid, T) -> |
| 1340 | + {timer, {sac, node_disconnected, |
| 1341 | + #{connection_pid => Pid}}, T}. |
| 1342 | + |
1298 | 1343 | ts() ->
|
1299 | 1344 | erlang:system_time(millisecond).
|
1300 | 1345 |
|
0 commit comments