./ct_report/coverage/mongoose_backend.COVER.html

1 -module(mongoose_backend).
2
3 %% API
4 -export([init/4,
5 call/4,
6 call_tracked/4,
7 is_exported/4,
8 get_backend_name/2]).
9
10 %% remove after mongoose_rdbms is refactored not to use dynamically compiled backend
11 -ignore_xref([get_backend_name/2]).
12
13 %% For debugging and tests
14 -export([get_backend_module/2]).
15 -ignore_xref([get_backend_module/2]).
16
17 -type function_name() :: atom().
18 -type main_module() :: module().
19 -type backend_module() :: module().
20 -type host_type_or_global() :: mongooseim:host_type_or_global().
21
22 -spec init(HostType :: host_type_or_global(),
23 MainModule :: main_module(),
24 TrackedFuns :: [function_name()],
25 Opts :: map()) -> ok.
26 init(HostType, MainModule, TrackedFuns, Opts) ->
27 1583 Backend = maps:get(backend, Opts, mnesia),
28 1583 BackendModule = backend_module(MainModule, Backend),
29 1583 persist_backend_name(HostType, MainModule, Backend, BackendModule),
30 1583 try
31 1583 mongoose_instrument:set_up(instrumentation(HostType, BackendModule, TrackedFuns))
32 catch error:#{what := event_already_registered} ->
33 %% The same backend can be initialized more than once because:
34 %% - either it is global, and a module initializes it for each host type
35 %% - or the module (or the entire app) was restarted
36 358 ok
37 end.
38
39 backend_module(Module, Backend) ->
40 1583 list_to_atom(atom_to_list(Module) ++ "_" ++ atom_to_list(Backend)).
41
42 backend_key(HostType, MainModule) ->
43 403526 {backend_module, HostType, MainModule}.
44
45 backend_name_key(HostType, MainModule) ->
46 13556 {backend_name, HostType, MainModule}.
47
48 -spec instrumentation(host_type_or_global(), module(), [function_name()]) ->
49 [mongoose_instrument:spec()].
50 instrumentation(HostType, BackendModule, FunNames) ->
51 1583 [{BackendModule, labels(HostType, FunName),
52 1583 #{metrics => #{count => spiral, time => histogram}}} || FunName <- FunNames].
53
54 -spec labels(host_type_or_global(), function_name()) -> mongoose_instrument:labels().
55 labels(global, FunName) ->
56 221586 #{function => FunName};
57 labels(HostType, FunName) ->
58 35222 #{function => FunName, host_type => HostType}.
59
60 persist_backend_name(HostType, MainModule, Backend, BackendModule) ->
61 1583 ModuleKey = backend_key(HostType, MainModule),
62 1583 persistent_term:put(ModuleKey, BackendModule),
63 1583 NameKey = backend_name_key(HostType, MainModule),
64 1583 persistent_term:put(NameKey, Backend).
65
66 %% @doc Get a backend module, stored in init.
67 -spec get_backend_module(HostType :: host_type_or_global(),
68 MainModule :: main_module()) ->
69 BackendModule :: backend_module().
70 get_backend_module(HostType, MainModule) ->
71 401943 ModuleKey = backend_key(HostType, MainModule),
72 401943 persistent_term:get(ModuleKey).
73
74 %% @doc Get a backend name, like `pgsql', stored in init.
75 -spec get_backend_name(HostType :: host_type_or_global(),
76 MainModule :: main_module()) -> BackendName :: atom().
77 get_backend_name(HostType, MainModule) ->
78 11973 Key = backend_name_key(HostType, MainModule),
79 11973 persistent_term:get(Key).
80
81 -spec call(HostType :: host_type_or_global(),
82 MainModule :: main_module(),
83 FunName :: function_name(),
84 Args :: [term()]) -> term().
85 call(HostType, MainModule, FunName, Args) ->
86 149443 BackendModule = get_backend_module(HostType, MainModule),
87 149443 erlang:apply(BackendModule, FunName, Args).
88
89 -spec call_tracked(HostType :: host_type_or_global(),
90 MainModule :: main_module(),
91 FunName :: function_name(),
92 Args :: [term()]) -> term().
93 call_tracked(HostType, MainModule, FunName, Args) ->
94 250825 BackendModule = get_backend_module(HostType, MainModule),
95 250825 mongoose_instrument:span(BackendModule, labels(HostType, FunName),
96 BackendModule, FunName, Args,
97 250825 fun(Time, _Result) -> #{args => Args, time => Time, count => 1} end).
98
99 -spec is_exported(HostType :: host_type_or_global(),
100 MainModule :: main_module(),
101 FunName :: function_name(),
102 Arity :: integer()) -> boolean().
103 is_exported(HostType, MainModule, Function, Arity) ->
104 376 BackendModule = get_backend_module(HostType, MainModule),
105 376 erlang:function_exported(BackendModule, Function, Arity).
Line Hits Source