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