Skip to content

Commit

Permalink
Merge pull request #3560 from esl/mu-local-iq-response-without-mnesia
Browse files Browse the repository at this point in the history
Don't use mnesia for IQ response tracking

The code I am touching here is a bit old and a bit hairy.
I honestly didn't read that one and it took sometime to understand why we use mnesia there to begin with.

So, TLDR:

    the code I am touching allows to route an IQ from the SERVER to the CLIENT (the opposite way they usually go).
    it is used in mod_ping.
    though, the last thing I want is to replicate data, that is used by mod_ping in a big cluster (because of how often it is written).
    in the real life, that iq_response would never do RPC calls (at least for mod_ping, because the process sending IQ and receiving IQ is a c2s process). We still need to test it though :(

Proposed changes include:

    This change removes replication for IQ response tracking (useful in the big clusters, that use mod_ping)
    We use IQ IDs to locate the metadata for the IQ instead
  • Loading branch information
NelsonVides authored Mar 22, 2022
2 parents 17fbc73 + f476beb commit bda07f6
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 148 deletions.
1 change: 1 addition & 0 deletions big_tests/default.spec
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
{suites, "tests", mam_send_message_SUITE}.
{suites, "tests", dynamic_domains_SUITE}.
{suites, "tests", auth_methods_for_c2s_SUITE}.
{suites, "tests", local_iq_SUITE}.

{config, ["test.config"]}.
{logdir, "ct_report"}.
Expand Down
1 change: 1 addition & 0 deletions big_tests/dynamic_domains.spec
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@

{suites, "tests", domain_removal_SUITE}.
{suites, "tests", auth_methods_for_c2s_SUITE}.
{suites, "tests", local_iq_SUITE}.

{config, ["dynamic_domains.config", "test.config"]}.

Expand Down
102 changes: 102 additions & 0 deletions big_tests/tests/local_iq_SUITE.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
-module(local_iq_SUITE).

-include_lib("common_test/include/ct.hrl").
-include_lib("eunit/include/eunit.hrl").
-include_lib("exml/include/exml.hrl").

-compile([export_all, nowarn_export_all]).
-import(distributed_helper, [mim/0, mim2/0, require_rpc_nodes/1, rpc/4, subhost_pattern/1]).
-import(domain_helper, [host_type/0, secondary_host_type/0]).

suite() ->
require_rpc_nodes([mim, mim2]).

all() ->
[{group, iq_group}].

groups() ->
[{iq_group, [], cases()}].

cases() ->
[process_iq_works_across_multiple_nodes,
process_iq_timeout].

%%--------------------------------------------------------------------
%% Init & teardown
%%--------------------------------------------------------------------

init_per_suite(Config) ->
distributed_helper:add_node_to_cluster(mim2(), Config),
mongoose_helper:inject_module(mim(), ?MODULE, reload),
mongoose_helper:inject_module(mim2(), ?MODULE, reload),
escalus:init_per_suite(Config).

end_per_suite(Config) ->
escalus:end_per_suite(Config).

init_per_group(iq_group, Config) ->
Config.

end_per_group(iq_group, Config) ->
escalus_fresh:clean(),
Config.

init_per_testcase(Testcase, Config) ->
escalus:init_per_testcase(Testcase, Config).

end_per_testcase(Testcase, Config) ->
escalus:end_per_testcase(Testcase, Config).

%%--------------------------------------------------------------------
%% Tests
%%--------------------------------------------------------------------

process_iq_works_across_multiple_nodes(Config) ->
%% Alice connects to node1
F = fun(Alice) ->
route_iq(Alice, undefined),
Stanza = escalus:wait_for_stanza(Alice),
escalus:assert(is_iq_get, [], Stanza),
escalus_client:send(Alice, escalus_stanza:iq_result(Stanza)),
receive
{result, _CbFrom, _CbTo, _CbAcc, _CbIQ} -> ok
after 5000 -> ct:fail(timeout_waiting_for_result)
end
end,
escalus:fresh_story(Config, [{alice, 1}], F).

process_iq_timeout(Config) ->
F = fun(Alice) ->
route_iq(Alice, 1),
Stanza = escalus:wait_for_stanza(Alice),
escalus:assert(is_iq_get, [], Stanza),
receive
{result, _CbFrom, _CbTo, _CbAcc, CbIQ} -> timeout = CbIQ
after 5000 -> ct:fail(timeout_waiting_for_result)
end
end,
escalus:fresh_story(Config, [{alice, 1}], F).

%%--------------------------------------------------------------------
%% Helpers
%%--------------------------------------------------------------------

route_iq(Alice, Timeout) ->
Jid = escalus_client:full_jid(Alice),
Server = escalus_client:server(Alice),
To = jid:from_binary(Jid),
From = jid:from_binary(Server),
Query = #xmlel{name = <<"query">>,
attrs = [{<<"xmlns">>, <<"cooltestns">>}]},
Xml = #xmlel{name = <<"iq">>,
attrs = [{<<"type">>, <<"get">>},
{<<"from">>, Server}, {<<"to">>, Jid}],
children = [Query]},
Acc = rpc(mim(), mongoose_acc, new,
[#{location => #{}, lserver => Server, element => Xml}]),
IQ = rpc(mim(), jlib, iq_query_info, [Xml]),
Self = self(),
Callback = fun(CbFrom, CbTo, CbAcc, CbIQ) ->
Self ! {result, CbFrom, CbTo, CbAcc, CbIQ}, CbAcc end,
Args = [From, To, Acc, IQ, Callback, Timeout],
rpc(mim2(), ejabberd_local, route_iq, Args).
Loading

0 comments on commit bda07f6

Please sign in to comment.