Skip to content

Commit efaf7c4

Browse files
committed
rabbit_khepri: Implement proper is_virgin_node/0 detection
[Why] The previous implementation checked if the store was empty. This part is unchanged. However if `is_empty/0` returned an error, typically because the store was stopped, it would consider that the node is also virgin. This is a wrong approximation because an admin could have executed `rabbitmqctl stop_app` before something checks the node is virgin. [How] With this patch, we introduce `rabbit_khepri:is_virgin_node/0`. It will start the store if it is stopped, then it will query if it is empty. It will stop the store again if it was stopped initially. This way, we have a more accurate answer to the question.
1 parent 3cc677b commit efaf7c4

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

deps/rabbit/src/rabbit_db.erl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,7 @@ is_virgin_node_using_mnesia() ->
231231
rabbit_mnesia:is_virgin_node().
232232

233233
is_virgin_node_using_khepri() ->
234-
case rabbit_khepri:is_empty() of
235-
{error, _} -> true;
236-
IsEmpty -> IsEmpty
237-
end.
234+
rabbit_khepri:is_virgin_node().
238235

239236
-spec is_virgin_node(Node) -> IsVirgin | undefined when
240237
Node :: node(),

deps/rabbit/src/rabbit_khepri.erl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
setup/1,
105105
init/1,
106106
reset/0,
107+
is_virgin_node/0,
107108

108109
dir/0,
109110
get_ra_cluster_name/0,
@@ -297,10 +298,16 @@ setup(_Context) ->
297298
exit(Error)
298299
end.
299300

301+
is_ra_system_running() ->
302+
rabbit_ra_systems:is_running(?RA_SYSTEM).
303+
300304
ensure_ra_system_started() ->
301305
{ok, _} = application:ensure_all_started(khepri),
302306
ok = rabbit_ra_systems:ensure_ra_system_started(?RA_SYSTEM).
303307

308+
ensure_ra_system_stopped() ->
309+
ok = rabbit_ra_systems:ensure_ra_system_stopped(?RA_SYSTEM).
310+
304311
retry_timeout() ->
305312
case application:get_env(rabbit, khepri_leader_wait_retry_timeout) of
306313
{ok, T} when is_integer(T) andalso T >= 0 -> T;
@@ -385,6 +392,30 @@ reset() ->
385392
throw({error, rabbitmq_unexpectedly_running})
386393
end.
387394

395+
is_virgin_node() ->
396+
IsSystemRunning = is_ra_system_running(),
397+
IsStoreRunning = khepri_cluster:is_store_running(?STORE_ID),
398+
case IsSystemRunning of
399+
true -> ok;
400+
false -> ensure_ra_system_started()
401+
end,
402+
case IsStoreRunning of
403+
true -> ok;
404+
false -> setup()
405+
end,
406+
407+
IsEmpty = is_empty() =:= true,
408+
409+
case IsStoreRunning of
410+
true -> ok;
411+
false -> _ = khepri:stop(?RA_CLUSTER_NAME)
412+
end,
413+
case IsSystemRunning of
414+
true -> ok;
415+
false -> ensure_ra_system_stopped()
416+
end,
417+
IsEmpty.
418+
388419
-spec dir() -> Dir when
389420
Dir :: file:filename_all().
390421
%% @doc Returns the Khepri store directory.

deps/rabbit/src/rabbit_ra_systems.erl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
-export([setup/0,
1515
setup/1,
1616
all_ra_systems/0,
17+
is_running/1,
1718
are_running/0,
1819
ensure_ra_system_started/1,
1920
ensure_ra_system_stopped/1,
@@ -46,6 +47,20 @@ all_ra_systems() ->
4647
[coordination,
4748
quorum_queues].
4849

50+
-spec is_running(RaSystem) -> IsRunning when
51+
RaSystem :: ra_system_name(),
52+
IsRunning :: boolean().
53+
54+
is_running(RaSystem) ->
55+
try
56+
%% FIXME: We hard-code the name of an internal Ra process here.
57+
Children = supervisor:which_children(ra_systems_sup),
58+
is_ra_system_running(Children, RaSystem)
59+
catch
60+
exit:{noproc, _} ->
61+
false
62+
end.
63+
4964
-spec are_running() -> AreRunning when
5065
AreRunning :: boolean().
5166

0 commit comments

Comments
 (0)