Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pools/per host type #4229

Merged
merged 2 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions big_tests/tests/mod_event_pusher_rabbit_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
-define(CHAT_MSG_RECV_TOPIC, <<"custom_chat_msg_recv_topic">>).
-define(GROUP_CHAT_MSG_SENT_TOPIC, <<"custom_group_chat_msg_sent_topic">>).
-define(GROUP_CHAT_MSG_RECV_TOPIC, <<"custom_group_chat_msg_recv_topic">>).
-define(WPOOL_CFG, #{scope => host,
-define(WPOOL_CFG, #{scope => host_type,
opts => #{workers => 20, strategy => best_worker, call_timeout => 5000}}).
-define(IF_EXCHANGE_EXISTS_RETRIES, 30).
-define(WAIT_FOR_EXCHANGE_INTERVAL, 100). % ms
Expand Down Expand Up @@ -178,7 +178,7 @@ end_per_testcase(CaseName, Config) ->
rabbit_pool_starts_with_default_config(_Config) ->
%% GIVEN
Domain = domain(),
DefaultWpoolConfig = #{type => rabbit, scope => host, tag => rabbit_event_pusher_default,
DefaultWpoolConfig = #{type => rabbit, scope => host_type, tag => rabbit_event_pusher_default,
opts => #{workers => 10, strategy => best_worker, call_timeout => 5000},
conn_opts => #{amqp_port => 5672, confirms_enabled => false, max_worker_queue_len => 1000}},
RabbitWpool = {rabbit, Domain, rabbit_event_pusher_default},
Expand Down
2 changes: 1 addition & 1 deletion big_tests/tests/push_http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ start_pool() ->
PoolOpts = #{strategy => random_worker, call_timeout => 5000, workers => 10},
ConnOpts = #{host => http_notifications_host(), request_timeout => 5000},
Pool = config([outgoing_pools, http, http_pool],
#{scope => host, opts => PoolOpts, conn_opts => ConnOpts}),
#{scope => host_type, opts => PoolOpts, conn_opts => ConnOpts}),
[{ok, _Pid}] = rpc(mongoose_wpool, start_configured_pools, [[Pool], [<<"localhost">>]]).

stop_pool() ->
Expand Down
16 changes: 12 additions & 4 deletions doc/configuration/outgoing-connections.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ This allows you to create multiple dedicated pools of the same type.
## General pool options

### `outgoing_pools.*.*.scope`
* **Syntax:** string, one of:`"global"`, `"host"`, `"single_host"`
* **Syntax:** string, one of:`"global"`, `"host_type"`, `"single_host_type"`
* **Default:** `"global"`
* **Example:** `scope = "host"`
* **Example:** `scope = "host_type"`

### `outgoing_pools.*.*.host_type`
* **Syntax:** string
* **Default:** no default; required if `"single_host_type"` scope is specified
* **Example:** `host_type = "basic_host_type"`

### `outgoing_pools.*.*.host`
* **Syntax:** string
Expand All @@ -27,13 +32,16 @@ This allows you to create multiple dedicated pools of the same type.
`scope` can be set to:

* `global` - meaning that the pool will be started once no matter how many XMPP hosts are served by MongooseIM
* `host` - the pool will be started for each XMPP host or host type served by MongooseIM
* `single_host` - the pool will be started for the selected host or host type only (you must provide the name).
* `host_type` - the pool will be started for each XMPP host or host type served by MongooseIM
* `single_host_type` - the pool will be started for the selected host or host type only (you must provide the name).

!!! Note
A pool with scope `global` and tag `default` is used by services that are not configured by host_type, like `service_domain_db` or `service_mongoose_system_metrics`, or by modules that don't support dynamic domains, like `mod_pubsub`.
If a global default pool is not configured, these services will fail.

!!! Note
`host` and `single_host` are still supported and behave equivalent to `host_type` and `single_host_type` respectively; however, they are deprecated in favour of the latter.

## Worker pool options

All pools are managed by the [inaka/worker_pool](https://github.com/inaka/worker_pool) library.
Expand Down
4 changes: 4 additions & 0 deletions doc/migrations/6.2.0_x.x.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ There is a new column in the `mam_message` table in the database, which is used
## Roster

`mod_roster` was internally refactored to modernise and improve the performance of the code, but as a side-effect, some database migrations need to be carried. See the migrations for Postgres, MySQL and MSSQL in the [`priv/migrations`](https://github.com/esl/MongooseIM/tree/master/priv/migrations) directory.

## Outgoing pools

Pools now take `host_type` and `single_host_type` instead of `host` and `single_host` in their scope, see [outgoing pools](../configuration/outgoing-connections.md) for more information.
17 changes: 13 additions & 4 deletions src/config/mongoose_config_spec.erl
Original file line number Diff line number Diff line change
Expand Up @@ -476,8 +476,12 @@

outgoing_pool_extra(Type) ->
#section{items = #{<<"scope">> => #option{type = atom,
validate = {enum, [global, host, single_host]}},
<<"host">> => #option{type = binary,
validate = {enum, [global,
host_type, single_host_type,
host, single_host]}}, %% TODO deprecated
<<"host_type">> => #option{type = binary,
validate = non_empty},
<<"host">> => #option{type = binary, %% TODO deprecated
validate = non_empty},
<<"connection">> => outgoing_pool_connection(Type)
},
Expand Down Expand Up @@ -1078,19 +1082,24 @@
end.

process_pool([Tag, Type|_], AllOpts = #{scope := ScopeIn, connection := Connection}) ->
Scope = pool_scope(ScopeIn, maps:get(host, AllOpts, none)),
Scope = pool_scope(ScopeIn, maps:get(host_type, AllOpts, maps:get(host, AllOpts, none))),
Opts = maps:without([scope, host, connection], AllOpts),
#{type => b2a(Type),
scope => Scope,
tag => b2a(Tag),
opts => Opts,
conn_opts => Connection}.

pool_scope(single_host_type, none) ->
error(#{what => pool_single_host_type_not_specified,

Check warning on line 1094 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1094

Added line #L1094 was not covered by tests
text => <<"\"host_type\" option is required if \"single_host_type\" is used.">>});
pool_scope(single_host, none) ->
error(#{what => pool_single_host_not_specified,
text => <<"\"host\" option is required if \"single_host\" is used.">>});
pool_scope(single_host_type, HostType) -> HostType;

Check warning on line 1099 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1099

Added line #L1099 was not covered by tests
pool_scope(single_host, Host) -> Host;
pool_scope(host, none) -> host;
pool_scope(host, none) -> host_type;
pool_scope(host_type, none) -> host_type;

Check warning on line 1102 in src/config/mongoose_config_spec.erl

View check run for this annotation

Codecov / codecov/patch

src/config/mongoose_config_spec.erl#L1101-L1102

Added lines #L1101 - L1102 were not covered by tests
pool_scope(global, none) -> global.

process_ldap_connection(ConnOpts = #{port := _}) -> ConnOpts;
Expand Down
6 changes: 3 additions & 3 deletions src/wpool/mongoose_wpool.erl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
| rabbit | ldap.

%% Config scope
-type scope() :: global | host | mongooseim:host_type().
-type scope() :: global | host_type | mongooseim:host_type().
-type host_type_or_global() :: mongooseim:host_type_or_global().

-type tag() :: atom().
Expand Down Expand Up @@ -361,9 +361,9 @@ make_callback_module_name(PoolType) ->
expand_pools(Pools, HostTypes) ->
%% First we select only pools for a specific vhost
HostSpecific = [{Type, HT, Tag} || #{type := Type, scope := HT, tag := Tag} <- Pools, is_binary(HT)],
%% Then we expand all pools with `host` as HostType parameter but using host specific configs
%% Then we expand all pools with `host_type` as HostType parameter but using host_type specific configs
%% if they were provided
F = fun(M = #{type := PoolType, scope := host, tag := Tag}) ->
F = fun(M = #{type := PoolType, scope := host_type, tag := Tag}) ->
[M#{scope => HostType} || HostType <- HostTypes,
not lists:member({PoolType, HostType, Tag}, HostSpecific)];
(Other) -> [Other]
Expand Down
2 changes: 1 addition & 1 deletion test/auth_http_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ init_per_suite(Config) ->
Config.

pool_opts() ->
#{scope => host,
#{scope => host_type,
opts => #{strategy => random_worker, call_timeout => 5000, workers => 20},
conn_opts => #{host => ?AUTH_HOST, path_prefix => <<"/auth/">>}}.

Expand Down
4 changes: 2 additions & 2 deletions test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,12 @@ options("outgoing_pools") ->
opts => #{workers => 50},
conn_opts => #{host => "https://localhost:8443",
request_timeout => 2000}},
#{type => ldap, scope => host, tag => default,
#{type => ldap, scope => host_type, tag => default,
opts => #{workers => 5},
conn_opts => #{password => <<"ldap-admin-password">>,
root_dn => <<"cn=admin,dc=example,dc=com">>,
servers => ["ldap-server.example.com"]}},
#{type => rabbit, scope => host, tag => event_pusher,
#{type => rabbit, scope => host_type, tag => event_pusher,
opts => #{workers => 20},
conn_opts => #{confirms_enabled => true,
max_worker_queue_len => 100}},
Expand Down
6 changes: 5 additions & 1 deletion test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -884,10 +884,14 @@ pool_scope(_Config) ->
P = [outgoing_pools, 1, scope],
Required = #{<<"connection">> => #{<<"host">> => <<"http://localhost">>}},
T = fun(Opts) -> pool_raw(<<"http">>, <<"default">>, maps:merge(Required, Opts)) end,
?cfg(P, host, T(#{<<"scope">> => <<"host">>})),
?cfg(P, host_type, T(#{<<"scope">> => <<"host">>})),
?cfg(P, host_type, T(#{<<"scope">> => <<"host_type">>})),
?cfg(P, <<"localhost">>, T(#{<<"scope">> => <<"single_host">>, <<"host">> => <<"localhost">>})),
?cfg(P, <<"localhost">>, T(#{<<"scope">> => <<"single_host_type">>, <<"host_type">> => <<"localhost">>})),
?err(T(#{<<"host">> => <<"localhost">>})), % missing scope
?err(T(#{<<"host_type">> => <<"localhost">>})), % missing scope
?err(T(#{<<"scope">> => <<"single_host">>})), % missing host
?err(T(#{<<"scope">> => <<"single_host_type">>})), % missing host type
?err(T(#{<<"scope">> => <<"whatever">>})).

pool_rdbms(_Config) ->
Expand Down
6 changes: 3 additions & 3 deletions test/config_parser_SUITE_data/outgoing_pools.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
default_server_domain = "localhost"

[outgoing_pools.redis.global_distrib]
scope = "single_host"
scope = "single_host_type"
host = "localhost"
workers = 10

Expand Down Expand Up @@ -50,7 +50,7 @@
connection.host = "localhost"

[outgoing_pools.rabbit.event_pusher]
scope = "host"
scope = "host_type"
workers = 20

[outgoing_pools.rabbit.event_pusher.connection]
Expand All @@ -62,7 +62,7 @@
max_worker_queue_len = 100

[outgoing_pools.ldap.default]
scope = "host"
scope = "host_type"
workers = 5

[outgoing_pools.ldap.default.connection]
Expand Down
8 changes: 4 additions & 4 deletions test/mongoose_wpool_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ two_distinct_redis_pools_are_started(_C) ->
?assertMatch(#{host := "localhost2", port := 1806}, proplists:to_map(Props2)).

generic_pools_are_started_for_all_vhosts(_C) ->
Pools = [#{type => generic, scope => host, tag => default, opts => #{}, conn_opts => #{}}],
Pools = [#{type => generic, scope => host_type, tag => default, opts => #{}, conn_opts => #{}}],
StartRes = mongoose_wpool:start_configured_pools(Pools),
?assertMatch([_, _, _], StartRes),
?assertMatch([{generic, <<"a.com">>, default},
Expand All @@ -137,7 +137,7 @@ generic_pools_are_started_for_all_vhosts(_C) ->
ordsets:from_list(mongoose_wpool:get_pools())).

host_specific_pools_are_preserved(_C) ->
Pools = [#{type => generic, scope => host, tag => default, opts => #{}, conn_opts => #{}},
Pools = [#{type => generic, scope => host_type, tag => default, opts => #{}, conn_opts => #{}},
#{type => generic, scope => <<"b.com">>, tag => default,
opts => #{workers => 12}, conn_opts => #{}}],
Expanded = mongoose_wpool:expand_pools(Pools, [<<"a.com">>, <<"b.com">>, <<"c.eu">>]),
Expand All @@ -150,10 +150,10 @@ host_specific_pools_are_preserved(_C) ->
Expanded).

pools_for_different_tag_are_expanded_with_host_specific_config_preserved(_C) ->
Pools = [#{type => generic, scope => host, tag => default, opts => #{}, conn_opts => #{}},
Pools = [#{type => generic, scope => host_type, tag => default, opts => #{}, conn_opts => #{}},
#{type => generic, scope => <<"b.com">>, tag => default,
opts => #{workers => 12}, conn_opts => #{}},
#{type => generic, scope => host, tag => other_tag, opts => #{}, conn_opts => #{}}],
#{type => generic, scope => host_type, tag => other_tag, opts => #{}, conn_opts => #{}}],
Expanded = mongoose_wpool:expand_pools(Pools, [<<"a.com">>, <<"b.com">>, <<"c.eu">>]),
?assertMatch([#{type := generic, host_type := <<"a.com">>, tag := default,
opts := [], conn_opts := #{}},
Expand Down