Skip to content

Commit

Permalink
Fix a race condition in service_domain_db_suite.db_keeps_syncing_afte…
Browse files Browse the repository at this point in the history
…r_cluster_join

sync() assumes that sending message from mim() to mim2() node is instant

But it is not true, so check_for_updates message is received after sync_local call
in tests.

I.e. the following scenario fails:

1. Test node asks mim2() to insert a domain.
2. mim2() sends check_for_updates to mim() node.
3. Test node calls sync_local on mim() node.
4. mim() calls sync_local and replies to the test node.
5. mim() finally receives check_for_updates from mim2(), send in step 2.
  • Loading branch information
arcusfelis committed Aug 1, 2023
1 parent 6cef853 commit 139130e
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions src/domain/service_domain_db.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
-export([start_link/0]).
-export([enabled/0]).
-export([force_check_for_updates/0]).
-export([sync_local/0]).
-export([sync_local/0, ping/1]).

-ignore_xref([start_link/0, sync_local/0,
-ignore_xref([start_link/0, sync_local/0, ping/1,
init/1, handle_call/3, handle_cast/2, handle_info/2,
code_change/3, terminate/2]).

Expand Down Expand Up @@ -73,18 +73,34 @@ start_link() ->
enabled() ->
mongoose_service:is_loaded(?MODULE).

all_members() ->
pg:get_members(?SCOPE, ?GROUP).

Check warning on line 77 in src/domain/service_domain_db.erl

View check run for this annotation

Codecov / codecov/patch

src/domain/service_domain_db.erl#L77

Added line #L77 was not covered by tests

force_check_for_updates() ->
%% Send a broadcast message.
case pg:get_members(?SCOPE, ?GROUP) of
case all_members() of

Check warning on line 81 in src/domain/service_domain_db.erl

View check run for this annotation

Codecov / codecov/patch

src/domain/service_domain_db.erl#L81

Added line #L81 was not covered by tests
[_|_] = Pids ->
[Pid ! check_for_updates || Pid <- Pids],
ok;
_ ->
ok
end.

%% Ensure that all pending check_for_updates messages are received by this node,
%% even if they are sent by other nodes in the cluster.
%% We have to do an RPC to ensure there is nothing pending in the distributed communication buffers.
%% Used in tests.
sync_local() ->
gen_server:call(?MODULE, ping).
LocalPid = whereis(?MODULE),
true = is_pid(LocalPid),
Nodes = [node(Pid) || Pid <- all_members()],

Check warning on line 96 in src/domain/service_domain_db.erl

View check run for this annotation

Codecov / codecov/patch

src/domain/service_domain_db.erl#L94-L96

Added lines #L94 - L96 were not covered by tests
%% Ping from all nodes in the cluster
[pong = rpc:call(Node, ?MODULE, ping, [LocalPid]) || Node <- Nodes],
pong.

Check warning on line 99 in src/domain/service_domain_db.erl

View check run for this annotation

Codecov / codecov/patch

src/domain/service_domain_db.erl#L98-L99

Added lines #L98 - L99 were not covered by tests

-spec ping(pid()) -> pong.
ping(Pid) ->
gen_server:call(Pid, ping).

Check warning on line 103 in src/domain/service_domain_db.erl

View check run for this annotation

Codecov / codecov/patch

src/domain/service_domain_db.erl#L103

Added line #L103 was not covered by tests

%% ---------------------------------------------------------------------------
%% Server callbacks
Expand Down

0 comments on commit 139130e

Please sign in to comment.