./ct_report/coverage/mongoose_user_cache.COVER.html

1 -module(mongoose_user_cache).
2
3 -include("mongoose_config_spec.hrl").
4
5 -export([start_new_cache/3, stop_cache/2, handle_telemetry_event/4,
6 config_spec/0, process_cache_config/1]).
7
8 -export([is_member/3, get_entry/3, merge_entry/4, delete_user/3, delete_domain/3]).
9
10 -spec is_member(mongooseim:host_type(), module(), jid:jid()) -> boolean().
11 is_member(HostType, Module, Jid) ->
12 877 CacheName = cache_name(HostType, Module),
13 877 segmented_cache:is_member(CacheName, key(Jid)).
14
15 -spec get_entry(mongooseim:host_type(), module(), jid:jid()) -> term() | not_found.
16 get_entry(HostType, Module, Jid) ->
17 58 CacheName = cache_name(HostType, Module),
18 58 segmented_cache:get_entry(CacheName, key(Jid)).
19
20 -spec merge_entry(mongooseim:host_type(), module(), jid:jid(), map()) -> boolean().
21 merge_entry(HostType, Module, Jid, Entry) ->
22 444 CacheName = cache_name(HostType, Module),
23 444 segmented_cache:merge_entry(CacheName, key(Jid), Entry).
24
25 -spec delete_user(mongooseim:host_type(), module(), jid:jid()) -> true.
26 delete_user(HostType, Module, Jid) ->
27 3066 CacheName = cache_name(HostType, Module),
28 3066 segmented_cache:delete_entry(CacheName, key(Jid)).
29
30 -spec delete_domain(mongooseim:host_type(), module(), jid:lserver()) -> true.
31 delete_domain(HostType, Module, Domain) ->
32 1 CacheName = cache_name(HostType, Module),
33 1 segmented_cache:delete_pattern(CacheName, {{'_', Domain}, '_'}).
34
35
36 %% path: (host_config[].)modules.*.cache
37 config_spec() ->
38 606 #section{
39 items = #{<<"module">> => #option{type = atom, validate = {enum, [internal, mod_cache_users]}},
40 <<"strategy">> => #option{type = atom, validate = {enum, [fifo, lru]}},
41 <<"time_to_live">> => #option{type = int_or_infinity, validate = positive},
42 <<"number_of_segments">> => #option{type = integer, validate = positive}
43 },
44 process = fun ?MODULE:process_cache_config/1,
45 defaults = #{<<"module">> => internal,
46 <<"strategy">> => fifo,
47 <<"time_to_live">> => 480,
48 <<"number_of_segments">> => 3}
49 }.
50
51 %% If an external module is provided, disallow any other configuration key
52 process_cache_config(#{module := internal} = Config) ->
53
:-(
Config;
54 process_cache_config(#{module := Module}) ->
55
:-(
#{module => Module};
56 process_cache_config(Config) ->
57 44 Config.
58
59 -spec start_new_cache(mongooseim:host_type(), module(), gen_mod:module_opts()) -> any().
60 start_new_cache(HostType, Module, Opts) ->
61 172 case gen_mod:get_opt(module, Opts, internal) of
62 172 internal -> do_start_new_cache(HostType, Module, Opts);
63
:-(
_ -> ok
64 end.
65
66 do_start_new_cache(HostType, Module, Opts) ->
67 172 CacheName = gen_mod:get_module_proc(HostType, Module),
68 172 CacheOpts = #{scope => mim_scope,
69 merger_fun => fun maps:merge/2,
70 segment_num => gen_mod:get_opt(number_of_segments, Opts),
71 strategy => gen_mod:get_opt(strategy, Opts),
72 ttl => gen_mod:get_opt(time_to_live, Opts)},
73 172 Spec = #{id => CacheName, start => {segmented_cache, start_link, [CacheName, CacheOpts]},
74 restart => permanent, shutdown => 5000,
75 type => worker, modules => [segmented_cache]},
76 172 {ok, _} = ejabberd_sup:start_child(Spec),
77 172 create_metrics(HostType, Module, CacheName),
78 172 ok.
79
80 create_metrics(HostType, Module, CacheName) ->
81 172 telemetry:attach(CacheName,
82 [segmented_cache, CacheName, request, stop],
83 fun ?MODULE:handle_telemetry_event/4,
84 #{host_type => HostType, cache_name => CacheName, module => Module}),
85 172 mongoose_metrics:ensure_metric(HostType, [Module, hit], counter),
86 172 mongoose_metrics:ensure_metric(HostType, [Module, miss], counter),
87 172 mongoose_metrics:ensure_metric(HostType, [Module, latency], histogram).
88
89 handle_telemetry_event([segmented_cache, CacheName, request, stop],
90 #{duration := Latency},
91 #{hit := Hit},
92 #{host_type := HostType, cache_name := CacheName, module := Module}) ->
93 935 case Hit of
94 372 true -> mongoose_metrics:update(HostType, [Module, hit], 1);
95 563 false -> mongoose_metrics:update(HostType, [Module, miss], 1)
96 end,
97 935 mongoose_metrics:update(HostType, [Module, latency], Latency),
98 935 ok.
99
100 -spec stop_cache(mongooseim:host_type(), module()) -> ok.
101 stop_cache(HostType, Module) ->
102 170 case gen_mod:get_module_opt(HostType, Module, module, internal) of
103 170 internal -> ok = ejabberd_sup:stop_child(cache_name(HostType, Module));
104
:-(
_ConfiguredModule -> ok
105 end.
106
107 -spec cache_name(mongooseim:host_type(), module()) -> atom().
108 cache_name(HostType, Module) ->
109 4616 case gen_mod:get_module_opt(HostType, Module, module, internal) of
110 4616 internal -> gen_mod:get_module_proc(HostType, Module);
111
:-(
ConfiguredModule -> gen_mod:get_module_proc(HostType, ConfiguredModule)
112 end.
113
114 -compile({inline, [key/1]}).
115 -spec key(jid:jid()) -> jid:simple_bare_jid().
116 key(Jid) ->
117 4445 jid:to_lus(Jid).
Line Hits Source