./ct_report/coverage/service_domain_db.COVER.html

1 -module(service_domain_db).
2
3 -behaviour(mongoose_service).
4
5 -include("mongoose_config_spec.hrl").
6 -include("mongoose_logger.hrl").
7
8 %% Use a separate pg scope, which is started by ejabberd_sup
9 %% This prevents a bug when a default pg server is not running
10 -define(SCOPE, mim_scope).
11 -define(GROUP, service_domain_db_group).
12
13 -export([start/1, stop/0, restart/0, config_spec/0]).
14 -export([start_link/0]).
15 -export([enabled/0]).
16 -export([force_check_for_updates/0]).
17 -export([sync_local/0]).
18
19 -ignore_xref([start_link/0, sync_local/0,
20 init/1, handle_call/3, handle_cast/2, handle_info/2,
21 code_change/3, terminate/2]).
22
23 %% gen_server callbacks
24 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
25 terminate/2, code_change/3]).
26
27 %% ---------------------------------------------------------------------------
28 %% Client code
29
30 start(Opts) ->
31 224 mongoose_domain_sql:start(Opts),
32 224 ChildSpec =
33 {?MODULE,
34 {?MODULE, start_link, []},
35 permanent, infinity, worker, [?MODULE]},
36 224 supervisor:start_child(ejabberd_sup, ChildSpec),
37 224 mongoose_domain_db_cleaner:start(Opts),
38 224 ok.
39
40 stop() ->
41 222 mongoose_domain_db_cleaner:stop(),
42 222 supervisor:terminate_child(ejabberd_sup, ?MODULE),
43 222 supervisor:delete_child(ejabberd_sup, ?MODULE),
44 222 supervisor:terminate_child(ejabberd_sup, domain_pg),
45 222 supervisor:delete_child(ejabberd_sup, domain_pg),
46 222 ok.
47
48 restart() ->
49 %% if service goes out of sync with DB this interface
50 %% can be used to restart the service.
51 %% it's enough to just shut down gen_server, supervisor
52 %% will restart it.
53
:-(
gen_server:cast(?MODULE, reset_and_shutdown).
54
55 -spec config_spec() -> mongoose_config_spec:config_section().
56 config_spec() ->
57 72 #section{items = #{
58 <<"event_cleaning_interval">> => #option{type = integer,
59 validate = positive},
60 <<"event_max_age">> => #option{type = integer,
61 validate = positive},
62 <<"db_pool">> => #option{type = atom,
63 validate = pool_name}
64 }}.
65
66 start_link() ->
67 224 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
68
69 enabled() ->
70 396 mongoose_service:is_loaded(?MODULE).
71
72 force_check_for_updates() ->
73 %% Send a broadcast message.
74 63 case pg:get_members(?SCOPE, ?GROUP) of
75 [_|_] = Pids ->
76 63 [Pid ! check_for_updates || Pid <- Pids],
77 63 ok;
78 _ ->
79
:-(
ok
80 end.
81
82 sync_local() ->
83 54 gen_server:call(?MODULE, ping).
84
85 %% ---------------------------------------------------------------------------
86 %% Server callbacks
87
88 init([]) ->
89 224 pg:join(?SCOPE, ?GROUP, self()),
90 224 gen_server:cast(self(), initial_loading),
91 %% initial state will be set on initial_loading processing
92 224 {ok, #{}}.
93
94 handle_call(ping, _From, State) ->
95 54 {reply, pong, State};
96 handle_call(Request, From, State) ->
97
:-(
?UNEXPECTED_CALL(Request, From),
98
:-(
{reply, ok, State}.
99
100 handle_cast(initial_loading, State) ->
101 224 mongoose_domain_loader:initial_load(),
102 223 NewState = State#{check_for_updates_interval => 30000},
103 223 {noreply, handle_check_for_updates(NewState, true)};
104 handle_cast(reset_and_shutdown, State) ->
105 %% to ensure that domains table is re-read from
106 %% scratch, we must reset the last event id.
107
:-(
mongoose_loader_state:reset(),
108
:-(
{stop, shutdown, State};
109 handle_cast(Msg, State) ->
110
:-(
?UNEXPECTED_CAST(Msg),
111
:-(
{noreply, State}.
112
113 handle_info(check_for_updates, State) ->
114 221 {noreply, handle_check_for_updates(State, false)};
115 handle_info(Info, State) ->
116
:-(
?UNEXPECTED_INFO(Info),
117
:-(
{noreply, State}.
118
119 terminate(_Reason, _State) ->
120
:-(
ok.
121
122 code_change(_OldVsn, State, _Extra) ->
123
:-(
{ok, State}.
124
125 %% ---------------------------------------------------------------------------
126 %% Server helpers
127
128 handle_check_for_updates(State = #{check_for_updates_interval := Interval},
129 IsInitial) ->
130 444 maybe_cancel_timer(IsInitial, State),
131 444 receive_all_check_for_updates(),
132 444 mongoose_domain_loader:check_for_updates(),
133 438 TRef = erlang:send_after(Interval, self(), check_for_updates),
134 438 State#{check_for_updates_tref => TRef}.
135
136 maybe_cancel_timer(IsInitial, State) ->
137 444 TRef = maps:get(check_for_updates_tref, State, undefined),
138 444 case {IsInitial, TRef} of
139 223 {true, undefined} -> ok; %% TRef is not set the first time
140 221 {false, _} -> erlang:cancel_timer(TRef)
141 end.
142
143 receive_all_check_for_updates() ->
144 446 receive check_for_updates -> receive_all_check_for_updates() after 0 -> ok end.
Line Hits Source