21
21
22
22
-define (SERVER , ? MODULE ).
23
23
-define (INTERVAL , 1000 ).
24
+ -define (CUTOFF , ? INTERVAL * 3 ).
24
25
25
26
-record (? MODULE , {tbl :: ets :table (),
26
27
nodes = [] :: [node ()]}).
@@ -38,7 +39,7 @@ list_present() ->
38
39
% % TODO: change return type to ok | error?
39
40
exit (presence_server_not_running );
40
41
_ ->
41
- Cutoff = erlang :system_time (millisecond ) - 5000 ,
42
+ Cutoff = erlang :system_time (millisecond ) - ? CUTOFF ,
42
43
[N || {N , SeenMs } <- ets :tab2list (? MODULE ),
43
44
% % if it hasn't been seen since the cutoff
44
45
SeenMs > Cutoff ,
@@ -52,10 +53,10 @@ start_link() ->
52
53
53
54
init ([]) ->
54
55
process_flag (trap_exit , true ),
55
- Ref = ets :new (? MODULE , [set , named_table , public ]),
56
+ Ref = ets :new (? MODULE , [set , named_table , protected ]),
57
+ _ = erlang :send_after (? INTERVAL , self (), beat ),
56
58
Nodes = rabbit_nodes :list_members (),
57
- beat_all (Nodes ),
58
- erlang :send_after (? INTERVAL , self (), beat ),
59
+ _ = beat_all (Nodes ),
59
60
{ok , #? MODULE {tbl = Ref ,
60
61
nodes = Nodes }}.
61
62
@@ -69,27 +70,33 @@ handle_info(beat, #?MODULE{tbl = _Tbl,
69
70
nodes = Nodes } = State ) ->
70
71
_ = erlang :send_after (? INTERVAL , self (), beat ),
71
72
_ = beat_all (Nodes ),
72
- {noreply , State };
73
+ % % this will only be efficient to do this often once list_members
74
+ % % make use of the ra_leaderboard rather than calling into the local
75
+ % % khepri process
76
+ case rabbit_nodes :list_members () of
77
+ Nodes ->
78
+ {noreply , State };
79
+ NewNodes ->
80
+ {noreply , State #? MODULE {nodes = NewNodes }}
81
+ end ;
73
82
handle_info ({hb , Node }, #? MODULE {tbl = Tbl ,
74
83
nodes = _Nodes } = State ) ->
75
84
ets :insert (Tbl , {Node , erlang :system_time (millisecond )}),
76
85
{noreply , State };
77
- handle_info ({terminate , Node }, #? MODULE {tbl = Tbl ,
78
- nodes = _Nodes } = State ) ->
79
- ets :delete (Tbl , Node ),
86
+ handle_info ({terminate , Node }, #? MODULE {tbl = Tbl } = State ) ->
87
+ _ = ets :delete (Tbl , Node ),
80
88
{noreply , State };
81
89
handle_info (_Msg , State ) ->
82
90
{noreply , State }.
83
91
84
92
terminate (_Reason , #? MODULE {nodes = Nodes }) ->
85
- % % only send terminate if reason is `shutdown`?
93
+ % % TODO: only send terminate if reason is `shutdown`?
86
94
_ = send_terminate (Nodes ),
87
95
ok .
88
96
89
97
code_change (_OldVsn , State , _Extra ) ->
90
98
{ok , State }.
91
99
92
-
93
100
% % INTERNAL
94
101
95
102
beat_all (Nodes ) ->
0 commit comments