./ct_report/coverage/mod_global_distrib_outgoing_conns_sup.COVER.html

1 -module(mod_global_distrib_outgoing_conns_sup).
2
3 -behaviour(supervisor).
4
5 -include("mongoose.hrl").
6
7 -export([start_link/0, init/1]).
8 -export([add_server/1, get_connection/1, ensure_server_started/1]).
9
10 -ignore_xref([add_server/1, start_link/0]).
11
12 %%--------------------------------------------------------------------
13 %% API
14 %%--------------------------------------------------------------------
15
16 -spec start_link() -> {ok, pid()} | {error, any()}.
17 start_link() ->
18 21 supervisor:start_link({local, ?MODULE}, ?MODULE, []).
19
20 -spec add_server(Server :: jid:lserver()) -> ok | {error, any()}.
21 add_server(Server) ->
22 83 SupName = mod_global_distrib_utils:server_to_sup_name(Server),
23 83 ServerSupSpec = #{
24 id => SupName,
25 start => {mod_global_distrib_server_sup, start_link, [Server]},
26 restart => temporary,
27 shutdown => 5000,
28 type => supervisor,
29 modules => dynamic
30 },
31 83 case supervisor:start_child(?MODULE, ServerSupSpec) of
32 {ok, Pid} ->
33 78 ?LOG_INFO(#{what => gd_outgoing_conn_started,
34
:-(
server => Server, gd_pid => Pid}),
35 78 ok;
36 {error, {already_started, Pid}} ->
37 5 ?LOG_INFO(#{what => gd_outgoing_conn_already_started,
38
:-(
server => Server, gd_pid => Pid}),
39 5 ok;
40 Error ->
41
:-(
?LOG_ERROR(#{what => gd_outgoing_conn_start_failed,
42
:-(
server => Server, reason => Error}),
43
:-(
Error
44 end.
45
46 %% Call to get_connection blocks until a connection is available.
47 %% Currently the timeout is infinity.
48 %% This function is safe for concurrent calls if the outgoing pool is not present yet.
49 %% The first caller will be the one initiating pool startup and the others are blocked
50 %% in the meantime; then, everyone will use the pool initiated by the first caller.
51 %% TODO: Revise negative cases for this function.
52 -spec get_connection(Server :: jid:lserver()) -> pid().
53 get_connection(Server) ->
54 32 get_connection(Server, 5).
55
56 -spec get_connection(Server :: jid:lserver(), RetriesLeft :: non_neg_integer()) ->
57 pid() | no_return().
58 get_connection(Server, 0) ->
59 1 ?LOG_ERROR(#{what => gd_cannot_acquire_outgoing_connection, server => Server}),
60 1 throw({error, {cannot_acquire_outgoing_connection, Server}});
61 get_connection(Server, RetriesLeft) ->
62 47 case mod_global_distrib_server_sup:get_connection(Server) of
63 {error, not_available} ->
64 %% add_server is a synchronous call that, if succeeds,
65 %% returns after the outgoing conn layer is ready,
66 %% so we may retry immediately
67 16 add_server(Server),
68 16 get_connection(Server, RetriesLeft - 1);
69 {ok, Pid} ->
70 31 Pid
71 end.
72
73 -spec ensure_server_started(Server :: jid:lserver()) -> ok | {error, any()}.
74 ensure_server_started(Server) ->
75 569 case mod_global_distrib_server_sup:is_available(Server) of
76 67 false -> add_server(Server);
77 502 true -> ok
78 end.
79
80 %%--------------------------------------------------------------------
81 %% supervisor callback
82 %%--------------------------------------------------------------------
83
84 init(_) ->
85 21 SupFlags = #{ strategy => one_for_one, intensity => 5, period => 5 },
86 21 {ok, {SupFlags, []}}.
Line Hits Source