Skip to content

Commit

Permalink
Merge pull request #4068 from esl/cache_routing_callbacks
Browse files Browse the repository at this point in the history
Cache router, filter, and process handlers into funs
  • Loading branch information
arcusfelis authored Jul 27, 2023
2 parents 3e8bcca + c7074ee commit 4333abe
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 56 deletions.
1 change: 1 addition & 0 deletions src/config/mongoose_config_spec.erl
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ general() ->
wrap = global_config},
<<"routing_modules">> => #list{items = #option{type = atom,
validate = module},
process = fun xmpp_router:expand_routing_modules/1,
wrap = global_config},
<<"replaced_wait_timeout">> => #option{type = integer,
validate = positive,
Expand Down
9 changes: 3 additions & 6 deletions src/ejabberd_router.erl
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ route(From, To, #xmlel{} = Packet) ->
route(From, To, Acc) ->
?LOG_DEBUG(#{what => route, acc => Acc}),
El = mongoose_acc:element(Acc),
RoutingModules = routing_modules_list(),
RoutingModules = mongoose_router:routing_modules_list(),
NewAcc = route(From, To, Acc, El, RoutingModules),
?LOG_DEBUG(#{what => routing_result,
routing_result => mongoose_acc:get(router, result, {drop, undefined}, NewAcc),
Expand All @@ -137,7 +137,7 @@ route(From, To, Acc, El) ->
to_jid => To,
element => El }, Acc),
?LOG_DEBUG(#{what => route, acc => Acc1}),
RoutingModules = routing_modules_list(),
RoutingModules = mongoose_router:routing_modules_list(),
NewAcc = route(From, To, Acc1, El, RoutingModules),
?LOG_DEBUG(#{what => routing_result,
routing_result => mongoose_acc:get(router, result, {drop, undefined}, NewAcc),
Expand Down Expand Up @@ -375,14 +375,11 @@ code_change(_OldVsn, State, _Extra) ->
hooks() ->
[{node_cleanup, global, fun ?MODULE:routes_cleanup_on_nodedown/3, #{}, 90}].

routing_modules_list() ->
mongoose_config:get_opt(routing_modules).

-spec route(From :: jid:jid(),
To :: jid:jid(),
Acc :: mongoose_acc:t(),
Packet :: exml:element(),
[module()]) -> mongoose_acc:t().
[xmpp_router:t()]) -> mongoose_acc:t().
route(_From, _To, Acc, _Packet, []) ->
?LOG_ERROR(#{what => no_more_routing_modules, acc => Acc}),
mongoose_metrics:update(global, routingErrors, 1),
Expand Down
43 changes: 19 additions & 24 deletions src/mongoose_packet_handler.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,21 @@
-module(mongoose_packet_handler).
-author('piotr.nosek@erlang-solutions.com').

%%----------------------------------------------------------------------
%% Types
%%----------------------------------------------------------------------

-record(packet_handler, { module, extra }).

-type t() :: #packet_handler{
module :: module(),
extra :: map()
}.

-record(packet_handler, {
handler :: process_packet(),
extra :: extra()
}).
-type extra() :: map().
-type t() :: #packet_handler{}.
-export_type([t/0]).

%%----------------------------------------------------------------------
%% Callback declarations
%%----------------------------------------------------------------------

-callback process_packet(Acc :: mongoose_acc:t(), From ::jid:jid(), To ::jid:jid(),
El :: exml:element(), Extra :: map()) -> mongoose_acc:t().
-define(ARGS, Acc :: mongoose_acc:t(),
From :: jid:jid(),
To :: jid:jid(),
El :: exml:element(),
Extra :: extra()).
-type process_packet() :: fun((?ARGS) -> mongoose_acc:t()).
-callback process_packet(?ARGS) -> mongoose_acc:t().

%%----------------------------------------------------------------------
%% API
Expand All @@ -36,25 +32,24 @@
%% Getters
-export([module/1, extra/1]).

-ignore_xref([behaviour_info/1]).

-spec new(Module :: module()) -> t().
new(Module) ->
new(Module, #{}).

-spec new(Module :: module(), Extra :: map()) -> t().
-spec new(Module :: module(), Extra :: extra()) -> t().
new(Module, Extra) when is_atom(Module), is_map(Extra) ->
#packet_handler{ module = Module, extra = Extra }.
#packet_handler{handler = fun Module:process_packet/5, extra = Extra }.

-spec process(Handler :: t(),
Acc :: mongoose_acc:t(),
From ::jid:jid(),
To ::jid:jid(),
El :: exml:element()) -> mongoose_acc:t().
process(#packet_handler{ module = Module, extra = Extra }, Acc, From, To, El) ->
Module:process_packet(Acc, From, To, El, Extra).
process(#packet_handler{handler = ProcessPacket, extra = Extra }, Acc, From, To, El) ->
ProcessPacket(Acc, From, To, El, Extra).

module(#packet_handler{ module = Module }) ->
module(#packet_handler{handler = ProcessPacket }) ->
{_, Module} = erlang:fun_info(ProcessPacket, module),
Module.

extra(#packet_handler{ extra = Extra }) ->
Expand Down
18 changes: 11 additions & 7 deletions src/mongoose_router.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

-define(TABLE, ?MODULE).

-export([start/0, default_routing_modules/0]).
-export([start/0, routing_modules_list/0, default_routing_modules/0]).

-export([get_all_domains/0, lookup_route/1, is_registered_route/1,
register_route/2, unregister_route/1]).
Expand Down Expand Up @@ -47,9 +47,13 @@ start() ->
mongoose_metrics:ensure_metric(global, routingErrors, spiral).

default_routing_modules() ->
[mongoose_router_global,
mongoose_router_localdomain,
mongoose_router_external_localnode,
mongoose_router_external,
mongoose_router_dynamic_domains,
ejabberd_s2s].
List = [mongoose_router_global,
mongoose_router_localdomain,
mongoose_router_external_localnode,
mongoose_router_external,
mongoose_router_dynamic_domains,
ejabberd_s2s],
xmpp_router:expand_routing_modules(List).

routing_modules_list() ->
mongoose_config:get_opt(routing_modules).
46 changes: 30 additions & 16 deletions src/xmpp_router.erl
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,39 @@
%%%-------------------------------------------------------------------
-module(xmpp_router).

-callback route(From :: jid:jid(), To :: jid:jid(),
Acc :: mongoose_acc:t(), Packet :: exml:element()) ->
{done, mongoose_acc:t()} | {jid:jid(), jid:jid(), mongoose_acc:t(), exml:element()}.

-callback filter(From :: jid:jid(), To :: jid:jid(),
Acc :: mongoose_acc:t(), Packet :: exml:element()) ->
drop | {jid:jid(), jid:jid(), mongoose_acc:t(), exml:element()}.
-define(ARGS, From :: jid:jid(),
To :: jid:jid(),
Acc :: mongoose_acc:t(),
Packet :: exml:element()).
-record(router_handler, {
filter :: filter_fun(),
route :: route_fun()
}).
-type t() :: #router_handler{}.
-type filter_fun() :: fun((?ARGS) -> drop | filter()).
-type route_fun() :: fun((?ARGS) -> {done, mongoose_acc:t()} | filter()).
-type filter() :: {?ARGS}.
-export_type([filter/0, t/0]).

-callback route(?ARGS) -> {done, mongoose_acc:t()} | filter().
-callback filter(?ARGS) -> drop | filter().

-export([expand_routing_modules/1]).
-export([call_route/5, call_filter/5]).

-spec call_route(Module :: module(), From :: jid:jid(),
-spec call_route(Handler :: t(), From :: jid:jid(),
To :: jid:jid(), Acc :: mongoose_acc:t(), Packet :: exml:element()) ->
{done, mongoose_acc:t()} | {jid:jid(), jid:jid(), mongoose_acc:t(), exml:element()}.
call_route(Module, From, To, Acc, Packet) ->
Module:route(From, To, Acc, Packet).
{done, mongoose_acc:t()} | filter().
call_route(#router_handler{route = Route}, From, To, Acc, Packet) ->
Route(From, To, Acc, Packet).

-spec call_filter(Module :: module(), From :: jid:jid(),
To :: jid:jid(), Acc :: mongoose_acc:t(), Packet :: exml:element()) ->
drop | {jid:jid(), jid:jid(), mongoose_acc:t(), exml:element()}.
call_filter(Module, From, To, Acc, Packet) ->
Module:filter(From, To, Acc, Packet).
-spec call_filter(Handler :: t(), From :: jid:jid(),
To :: jid:jid(), Acc :: mongoose_acc:t(), Packet :: exml:element()) -> drop | filter().
call_filter(#router_handler{filter = Filter}, From, To, Acc, Packet) ->
Filter(From, To, Acc, Packet).

-spec expand_routing_modules([module()]) -> [t()].
expand_routing_modules(ModuleList) ->
[ #router_handler{filter = fun Module:filter/4,
route = fun Module:route/4}
|| Module <- ModuleList ].
2 changes: 1 addition & 1 deletion test/common/config_parser_helper.erl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ options("miscellaneous") ->
{rdbms_server_type, mssql},
{registration_timeout, 600},
{routing_modules,
[mongoose_router_global, mongoose_router_localdomain]},
xmpp_router:expand_routing_modules([mongoose_router_global, mongoose_router_localdomain])},
{services,
#{service_mongoose_system_metrics => #{initial_report => 20000,
periodic_report => 300000,
Expand Down
3 changes: 2 additions & 1 deletion test/config_parser_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ mongooseimctl_access_commands(_Config) ->

routing_modules(_Config) ->
?cfg(routing_modules, mongoose_router:default_routing_modules(), #{}), % default
?cfg(routing_modules, [mongoose_router_global, mongoose_router_localdomain],
?cfg(routing_modules,
xmpp_router:expand_routing_modules([mongoose_router_global, mongoose_router_localdomain]),
#{<<"general">> => #{<<"routing_modules">> => [<<"mongoose_router_global">>,
<<"mongoose_router_localdomain">>]}}),
?err(#{<<"general">> => #{<<"routing_modules">> => [<<"moongoose_router_global">>]}}).
Expand Down
3 changes: 2 additions & 1 deletion test/router_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ end_per_suite(_C) ->
ok.

init_per_group(routing, Config) ->
mongoose_config:set_opt(routing_modules, [xmpp_router_a, xmpp_router_b, xmpp_router_c]),
RoutingModules = [xmpp_router_a, xmpp_router_b, xmpp_router_c],
mongoose_config:set_opt(routing_modules, xmpp_router:expand_routing_modules(RoutingModules)),
gen_hook:start_link(),
ejabberd_router:start_link(),
Config;
Expand Down

0 comments on commit 4333abe

Please sign in to comment.