./ct_report/coverage/mod_event_pusher.COVER.html

1 %%==============================================================================
2 %% Copyright 2016 Erlang Solutions Ltd.
3 %%
4 %% Licensed under the Apache License, Version 2.0 (the "License");
5 %% you may not use this file except in compliance with the License.
6 %% You may obtain a copy of the License at
7 %%
8 %% http://www.apache.org/licenses/LICENSE-2.0
9 %%
10 %% Unless required by applicable law or agreed to in writing, software
11 %% distributed under the License is distributed on an "AS IS" BASIS,
12 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 %% See the License for the specific language governing permissions and
14 %% limitations under the License.
15 %%==============================================================================
16
17 -module(mod_event_pusher).
18 -author('konrad.zemek@erlang-solutions.com').
19
20 -behaviour(gen_mod).
21 -behaviour(mongoose_module_metrics).
22
23 -include("jlib.hrl").
24 -include("mod_event_pusher_events.hrl").
25 -include("mongoose_config_spec.hrl").
26
27 -type event() :: #user_status_event{} | #chat_event{} | #unack_msg_event{}.
28 -export_type([event/0]).
29
30 -export([deps/2, start/2, stop/1, config_spec/0, push_event/3]).
31
32 -export([config_metrics/1]).
33
34 -ignore_xref([behaviour_info/1]).
35
36 %%--------------------------------------------------------------------
37 %% Callbacks
38 %%--------------------------------------------------------------------
39
40 -callback push_event(Acc :: mongoose_acc:t(), Host :: jid:lserver(), Event :: event()) -> mongoose_acc:t().
41
42 %%--------------------------------------------------------------------
43 %% API
44 %%--------------------------------------------------------------------
45
46 %% @doc Pushes the event to each backend registered with the event_pusher.
47 -spec push_event(mongoose_acc:t(), Host :: jid:server(), Event :: event()) -> mongoose_acc:t().
48 push_event(Acc, Host, Event) ->
49 1022 lists:foldl(fun(B, Acc0) ->
50 987 B:push_event(Acc0, Host, Event) end,
51 Acc,
52 ets:lookup_element(ets_name(Host), backends, 2)).
53
54 %%--------------------------------------------------------------------
55 %% gen_mod API
56 %%--------------------------------------------------------------------
57
58 -spec deps(Host :: jid:server(), Opts :: proplists:proplist()) -> gen_mod:deps_list().
59 deps(_Host, Opts) ->
60 119 Backends = get_backends(Opts),
61 119 BackendDeps = [{B, DepOpts, hard} || {B, DepOpts} <- Backends],
62 119 [{mod_event_pusher_hook_translator, hard} | BackendDeps].
63
64 -spec start(Host :: jid:server(), Opts :: proplists:proplist()) -> any().
65 start(Host, Opts) ->
66 23 create_ets(Host),
67 23 Backends = get_backends(Opts),
68 23 ets:insert(ets_name(Host), {backends, [B || {B, _} <- Backends]}).
69
70 -spec stop(Host :: jid:server()) -> any().
71 stop(Host) ->
72 23 ets:delete(ets_name(Host)).
73
74 -spec config_spec() -> mongoose_config_spec:config_section().
75 config_spec() ->
76 160 BackendItems = [{atom_to_binary(B, utf8),
77 160 (translate_backend(B)):config_spec()} || B <- all_backends()],
78 160 #section{
79 items = #{<<"backend">> => #section{items = maps:from_list(BackendItems),
80 wrap = {kv, backends}}
81 }
82 }.
83
84 %%--------------------------------------------------------------------
85 %% Helpers
86 %%--------------------------------------------------------------------
87
88 -spec get_backends(Opts :: proplists:proplist()) -> [{module(), proplists:proplist()}].
89 get_backends(Opts) ->
90 142 {backends, Backends0} = lists:keyfind(backends, 1, Opts),
91 142 lists:foldr(fun add_backend/2, [], Backends0).
92
93 add_backend({http, Opts}, BackendList) ->
94 % http backend is treated somewhat differently - we allow configuration settings as if there
95 % were many modules, while here we put together a single list of settings for the http event
96 % pusher module. Thus, you can configure event pusher like:
97 %{mod_event_pusher,
98 % [{backends,
99 % [{http,
100 % [{path, "/push_here"},
101 % {callback_module, mod_event_pusher_http_one},
102 % {pool_name, http_pool}]
103 % },
104 % {http,
105 % [{path, "/push_there"},
106 % {callback_module, mod_event_pusher_http_two},
107 % {pool_name, http_pool}]
108 % }
109 % ]
110 % }]
111 36 HttpModName = translate_backend(http),
112 36 case lists:keyfind(HttpModName, 1, BackendList) of
113 false ->
114 30 [{HttpModName, [{configs, [Opts]}]} | BackendList];
115 {HttpModName, [{configs, O}]} ->
116 6 lists:keyreplace(HttpModName, 1, BackendList,
117 {HttpModName, [{configs, [Opts | O]}]})
118 end;
119 add_backend({Mod, Opts}, BackendList) ->
120 112 [{translate_backend(Mod), Opts} | BackendList].
121
122 -spec translate_backend(Backend :: atom()) -> module().
123 translate_backend(Backend) ->
124 788 list_to_atom(?MODULE_STRING ++ "_" ++ atom_to_list(Backend)).
125
126 -spec ets_name(Host :: jid:server()) -> atom().
127 ets_name(Host) ->
128 1091 gen_mod:get_module_proc(Host, ?MODULE).
129
130 -spec create_ets(Host :: jid:server()) -> any().
131 create_ets(Host) ->
132 23 Self = self(),
133 23 Heir = case whereis(ejabberd_sup) of
134
:-(
undefined -> none;
135
:-(
Self -> none;
136 23 Pid -> Pid
137 end,
138 23 ets:new(ets_name(Host), [public, named_table, {read_concurrency, true}, {heir, Heir, testing}]).
139
140 config_metrics(Host) ->
141
:-(
try
142
:-(
Opts = gen_mod:get_module_opts(Host, ?MODULE),
143
:-(
BackendsWithOpts = proplists:get_value(backends, Opts, none),
144
:-(
Backends = proplists:get_keys(BackendsWithOpts),
145
:-(
ReturnList = lists:map(pa:bind(fun get_backend/2, BackendsWithOpts), Backends),
146
:-(
lists:flatten(ReturnList)
147 catch
148
:-(
_:_ -> [{none, none}]
149 end.
150
151 get_backend(BackendsWithOpts, Backend) ->
152
:-(
case Backend of
153 push ->
154
:-(
PushOptions = proplists:get_value(push, BackendsWithOpts),
155
:-(
PushBackend = atom_to_list(proplists:get_value(backend, PushOptions, mnesia)),
156
:-(
[{backend, push}, {backend, list_to_atom("push_" ++ PushBackend)}];
157 Backend ->
158
:-(
{backend, Backend}
159 end.
160
161 all_backends() ->
162 160 [sns, push, http, rabbit].
Line Hits Source