[Tarantool-patches] [PATCH 1/1] [tosquash] raft: don't expose 'raft' name to public

Serge Petrenko sergepetrenko at tarantool.org
Tue Sep 29 17:36:06 MSK 2020


29.09.2020 00:05, Vladislav Shpilevoy пишет:
> Raft is a name of the algorithm of leader election and and sync
> replication. Its exposure to public has 2 issues: not everyone
> know what is raft, and such users won't understand the new
> box.cfg options as well as box.info.raft purpose; the options and
> info will outdate in case we every switch to anything from Raft.
>
> This patch makes it called 'leadership'. So from the options
> name and box.info section name it is clear what this is about.
> And less problems with potential switching to something after
> Raft.
Hi! Thanks for the patch!
As  discussed, let's replace `leadership_` with `election_`.

So that it'll be
`election_is_enabled`
`election_is_candidate`
`election_timeout`
`box.info.election`


> ---
> Branch: http://github.com/tarantool/tarantool/tree/gh-1146-raft
> Issue: https://github.com/tarantool/tarantool/issues/1146
>
>   src/box/box.cc                                |  59 ++++-----
>   src/box/box.h                                 |   6 +-
>   src/box/lua/cfg.cc                            |  18 +--
>   src/box/lua/info.c                            |   4 +-
>   src/box/lua/load_cfg.lua                      |  30 ++---
>   ...t_basic.result => leadership_basic.result} | 117 ++++++++---------
>   test/replication/leadership_basic.test.lua    | 117 +++++++++++++++++
>   ...aft_replica.lua => leadership_replica.lua} |   8 +-
>   test/replication/leadership_replica1.lua      |   1 +
>   test/replication/leadership_replica2.lua      |   1 +
>   test/replication/leadership_replica3.lua      |   1 +
>   test/replication/raft_basic.test.lua          | 118 ------------------
>   test/replication/raft_replica1.lua            |   1 -
>   test/replication/raft_replica2.lua            |   1 -
>   test/replication/raft_replica3.lua            |   1 -
>   15 files changed, 242 insertions(+), 241 deletions(-)
>   rename test/replication/{raft_basic.result => leadership_basic.result} (52%)
>   create mode 100644 test/replication/leadership_basic.test.lua
>   rename test/replication/{raft_replica.lua => leadership_replica.lua} (80%)
>   create mode 120000 test/replication/leadership_replica1.lua
>   create mode 120000 test/replication/leadership_replica2.lua
>   create mode 120000 test/replication/leadership_replica3.lua
>   delete mode 100644 test/replication/raft_basic.test.lua
>   delete mode 120000 test/replication/raft_replica1.lua
>   delete mode 120000 test/replication/raft_replica2.lua
>   delete mode 120000 test/replication/raft_replica3.lua
>
> diff --git a/src/box/box.cc b/src/box/box.cc
> index 957bf4d7a..2ca238c76 100644
> --- a/src/box/box.cc
> +++ b/src/box/box.cc
> @@ -478,33 +478,33 @@ box_check_uri(const char *source, const char *option_name)
>   }
>   
>   static int
> -box_check_raft_is_enabled(void)
> +box_check_leadership_is_enabled(void)
>   {
> -	int b = cfg_getb("raft_is_enabled");
> +	int b = cfg_getb("leadership_is_enabled");
>   	if (b < 0) {
> -		diag_set(ClientError, ER_CFG, "raft_is_enabled",
> +		diag_set(ClientError, ER_CFG, "leadership_is_enabled",
>   			 "the value must be a boolean");
>   	}
>   	return b;
>   }
>   
>   static int
> -box_check_raft_is_candidate(void)
> +box_check_leadership_is_candidate(void)
>   {
> -	int b = cfg_getb("raft_is_candidate");
> +	int b = cfg_getb("leadership_is_candidate");
>   	if (b < 0) {
> -		diag_set(ClientError, ER_CFG, "raft_is_candidate",
> +		diag_set(ClientError, ER_CFG, "leadership_is_candidate",
>   			 "the value must be a boolean");
>   	}
>   	return b;
>   }
>   
>   static double
> -box_check_raft_election_timeout(void)
> +box_check_leadership_election_timeout(void)
>   {
> -	double d = cfg_getd("raft_election_timeout");
> +	double d = cfg_getd("leadership_election_timeout");
>   	if (d <= 0) {
> -		diag_set(ClientError, ER_CFG, "raft_election_timeout",
> +		diag_set(ClientError, ER_CFG, "leadership_election_timeout",
>   			 "the value must be a positive number");
>   		return -1;
>   	}
> @@ -768,11 +768,11 @@ box_check_config(void)
>   	box_check_uri(cfg_gets("listen"), "listen");
>   	box_check_instance_uuid(&uuid);
>   	box_check_replicaset_uuid(&uuid);
> -	if (box_check_raft_is_enabled() < 0)
> +	if (box_check_leadership_is_enabled() < 0)
>   		diag_raise();
> -	if (box_check_raft_is_candidate() < 0)
> +	if (box_check_leadership_is_candidate() < 0)
>   		diag_raise();
> -	if (box_check_raft_election_timeout() < 0)
> +	if (box_check_leadership_election_timeout() < 0)
>   		diag_raise();
>   	box_check_replication();
>   	box_check_replication_timeout();
> @@ -797,9 +797,9 @@ box_check_config(void)
>   }
>   
>   int
> -box_set_raft_is_enabled(void)
> +box_set_leadership_is_enabled(void)
>   {
> -	int b = box_check_raft_is_enabled();
> +	int b = box_check_leadership_is_enabled();
>   	if (b < 0)
>   		return -1;
>   	raft_cfg_is_enabled(b);
> @@ -807,9 +807,9 @@ box_set_raft_is_enabled(void)
>   }
>   
>   int
> -box_set_raft_is_candidate(void)
> +box_set_leadership_is_candidate(void)
>   {
> -	int b = box_check_raft_is_candidate();
> +	int b = box_check_leadership_is_candidate();
>   	if (b < 0)
>   		return -1;
>   	raft_cfg_is_candidate(b);
> @@ -817,9 +817,9 @@ box_set_raft_is_candidate(void)
>   }
>   
>   int
> -box_set_raft_election_timeout(void)
> +box_set_leadership_election_timeout(void)
>   {
> -	double d = box_check_raft_election_timeout();
> +	double d = box_check_leadership_election_timeout();
>   	if (d < 0)
>   		return -1;
>   	raft_cfg_election_timeout(d);
> @@ -2777,23 +2777,24 @@ box_cfg_xc(void)
>   	fiber_gc();
>   	is_box_configured = true;
>   	/*
> -	 * Fill in Raft parameters after bootstrap. Before it is not possible -
> -	 * there may be Raft data to recover from WAL and snapshot. Also until
> -	 * recovery is done, it is not possible to write new records into WAL.
> -	 * It is also totally safe, because relaying is not started until the
> -	 * box is configured. So it can't happen, that this Raft node will try
> -	 * to relay to another Raft node without Raft enabled leading to
> +	 * Fill in leadership parameters after bootstrap. Before it is not
> +	 * possible - there may be relevant data to recover from WAL and
> +	 * snapshot. Also until recovery is done, it is not possible to write
> +	 * new records into WAL. It is also totally safe, because relaying is
> +	 * not started until the box is configured. So it can't happen, that
> +	 * this leadership-enabled node will try to relay to another
> +	 * leadership-enabled node without leadership enabled leading to
>   	 * disconnect.
>   	 */
> -	if (box_set_raft_is_candidate() != 0)
> +	if (box_set_leadership_is_candidate() != 0)
>   		diag_raise();
> -	if (box_set_raft_election_timeout() != 0)
> +	if (box_set_leadership_election_timeout() != 0)
>   		diag_raise();
>   	/*
> -	 * Raft is enabled last. So as all the parameters are installed by that
> -	 * time.
> +	 * Leadership is enabled last. So as all the parameters are installed by
> +	 * that time.
>   	 */
> -	if (box_set_raft_is_enabled() != 0)
> +	if (box_set_leadership_is_enabled() != 0)
>   		diag_raise();
>   
>   	title("running");
> diff --git a/src/box/box.h b/src/box/box.h
> index 637d10dd3..e55c30627 100644
> --- a/src/box/box.h
> +++ b/src/box/box.h
> @@ -245,9 +245,9 @@ void box_set_vinyl_memory(void);
>   void box_set_vinyl_max_tuple_size(void);
>   void box_set_vinyl_cache(void);
>   void box_set_vinyl_timeout(void);
> -int box_set_raft_is_enabled(void);
> -int box_set_raft_is_candidate(void);
> -int box_set_raft_election_timeout(void);
> +int box_set_leadership_is_enabled(void);
> +int box_set_leadership_is_candidate(void);
> +int box_set_leadership_election_timeout(void);
>   void box_set_replication_timeout(void);
>   void box_set_replication_connect_timeout(void);
>   void box_set_replication_connect_quorum(void);
> diff --git a/src/box/lua/cfg.cc b/src/box/lua/cfg.cc
> index 339b85f9d..44f7ec727 100644
> --- a/src/box/lua/cfg.cc
> +++ b/src/box/lua/cfg.cc
> @@ -270,25 +270,25 @@ lbox_cfg_set_worker_pool_threads(struct lua_State *L)
>   }
>   
>   static int
> -lbox_cfg_set_raft_is_enabled(struct lua_State *L)
> +lbox_cfg_set_leadership_is_enabled(struct lua_State *L)
>   {
> -	if (box_set_raft_is_enabled() != 0)
> +	if (box_set_leadership_is_enabled() != 0)
>   		luaT_error(L);
>   	return 0;
>   }
>   
>   static int
> -lbox_cfg_set_raft_is_candidate(struct lua_State *L)
> +lbox_cfg_set_leadership_is_candidate(struct lua_State *L)
>   {
> -	if (box_set_raft_is_candidate() != 0)
> +	if (box_set_leadership_is_candidate() != 0)
>   		luaT_error(L);
>   	return 0;
>   }
>   
>   static int
> -lbox_cfg_set_raft_election_timeout(struct lua_State *L)
> +lbox_cfg_set_leadership_election_timeout(struct lua_State *L)
>   {
> -	if (box_set_raft_election_timeout() != 0)
> +	if (box_set_leadership_election_timeout() != 0)
>   		luaT_error(L);
>   	return 0;
>   }
> @@ -406,9 +406,9 @@ box_lua_cfg_init(struct lua_State *L)
>   		{"cfg_set_vinyl_max_tuple_size", lbox_cfg_set_vinyl_max_tuple_size},
>   		{"cfg_set_vinyl_cache", lbox_cfg_set_vinyl_cache},
>   		{"cfg_set_vinyl_timeout", lbox_cfg_set_vinyl_timeout},
> -		{"cfg_set_raft_is_enabled", lbox_cfg_set_raft_is_enabled},
> -		{"cfg_set_raft_is_candidate", lbox_cfg_set_raft_is_candidate},
> -		{"cfg_set_raft_election_timeout", lbox_cfg_set_raft_election_timeout},
> +		{"cfg_set_leadership_is_enabled", lbox_cfg_set_leadership_is_enabled},
> +		{"cfg_set_leadership_is_candidate", lbox_cfg_set_leadership_is_candidate},
> +		{"cfg_set_leadership_election_timeout", lbox_cfg_set_leadership_election_timeout},
>   		{"cfg_set_replication_timeout", lbox_cfg_set_replication_timeout},
>   		{"cfg_set_replication_connect_quorum", lbox_cfg_set_replication_connect_quorum},
>   		{"cfg_set_replication_connect_timeout", lbox_cfg_set_replication_connect_timeout},
> diff --git a/src/box/lua/info.c b/src/box/lua/info.c
> index 8e1dbd497..d1d552d20 100644
> --- a/src/box/lua/info.c
> +++ b/src/box/lua/info.c
> @@ -579,7 +579,7 @@ lbox_info_listen(struct lua_State *L)
>   }
>   
>   static int
> -lbox_info_raft(struct lua_State *L)
> +lbox_info_leadership(struct lua_State *L)
>   {
>   	lua_createtable(L, 0, 4);
>   	lua_pushstring(L, raft_state_strs[raft.state]);
> @@ -611,7 +611,7 @@ static const struct luaL_Reg lbox_info_dynamic_meta[] = {
>   	{"vinyl", lbox_info_vinyl},
>   	{"sql", lbox_info_sql},
>   	{"listen", lbox_info_listen},
> -	{"raft", lbox_info_raft},
> +	{"leadership", lbox_info_leadership},
>   	{NULL, NULL}
>   };
>   
> diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua
> index 2c98fd837..d2d58356c 100644
> --- a/src/box/lua/load_cfg.lua
> +++ b/src/box/lua/load_cfg.lua
> @@ -86,9 +86,9 @@ local default_cfg = {
>       checkpoint_wal_threshold = 1e18,
>       checkpoint_count    = 2,
>       worker_pool_threads = 4,
> -    raft_is_enabled       = false,
> -    raft_is_candidate     = true,
> -    raft_election_timeout = 5,
> +    leadership_is_enabled = false,
> +    leadership_is_candidate = true,
> +    leadership_election_timeout = 5,
>       replication_timeout = 1,
>       replication_sync_lag = 10,
>       replication_sync_timeout = 300,
> @@ -166,9 +166,9 @@ local template_cfg = {
>       read_only           = 'boolean',
>       hot_standby         = 'boolean',
>       worker_pool_threads = 'number',
> -    raft_is_enabled       = 'boolean',
> -    raft_is_candidate     = 'boolean',
> -    raft_election_timeout = 'number',
> +    leadership_is_enabled = 'boolean',
> +    leadership_is_candidate = 'boolean',
> +    leadership_election_timeout = 'number',
>       replication_timeout = 'number',
>       replication_sync_lag = 'number',
>       replication_sync_timeout = 'number',
> @@ -285,9 +285,9 @@ local dynamic_cfg = {
>           require('title').update(box.cfg.custom_proc_title)
>       end,
>       force_recovery          = function() end,
> -    raft_is_enabled         = private.cfg_set_raft_is_enabled,
> -    raft_is_candidate       = private.cfg_set_raft_is_candidate,
> -    raft_election_timeout   = private.cfg_set_raft_election_timeout,
> +    leadership_is_enabled   = private.cfg_set_leadership_is_enabled,
> +    leadership_is_candidate = private.cfg_set_leadership_is_candidate,
> +    leadership_election_timeout = private.cfg_set_leadership_election_timeout,
>       replication_timeout     = private.cfg_set_replication_timeout,
>       replication_connect_timeout = private.cfg_set_replication_connect_timeout,
>       replication_connect_quorum = private.cfg_set_replication_connect_quorum,
> @@ -342,9 +342,9 @@ local dynamic_cfg_order = {
>       -- the new one. This should be fixed when box.cfg is able to
>       -- apply some parameters together and atomically.
>       replication_anon        = 250,
> -    raft_is_enabled         = 300,
> -    raft_is_candidate       = 310,
> -    raft_election_timeout   = 320,
> +    leadership_is_enabled       = 300,
> +    leadership_is_candidate     = 310,
> +    leadership_election_timeout = 320,
>   }
>   
>   local function sort_cfg_cb(l, r)
> @@ -362,9 +362,9 @@ local dynamic_cfg_skip_at_load = {
>       vinyl_cache             = true,
>       vinyl_timeout           = true,
>       too_long_threshold      = true,
> -    raft_is_enabled         = true,
> -    raft_is_candidate       = true,
> -    raft_election_timeout   = true,
> +    leadership_is_enabled   = true,
> +    leadership_is_candidate = true,
> +    leadership_election_timeout = true,
>       replication             = true,
>       replication_timeout     = true,
>       replication_connect_timeout = true,
> diff --git a/test/replication/raft_basic.result b/test/replication/leadership_basic.result
> similarity index 52%
> rename from test/replication/raft_basic.result
> rename to test/replication/leadership_basic.result
> index 3421227fb..51dc468e0 100644
> --- a/test/replication/raft_basic.result
> +++ b/test/replication/leadership_basic.result
> @@ -6,54 +6,56 @@ test_run = require('test_run').new()
>   -- gh-1146: Raft protocol for automated leader election.
>   --
>   
> -old_raft_election_timeout = box.cfg.raft_election_timeout
> +old_leadership_election_timeout = box.cfg.leadership_election_timeout
>    | ---
>    | ...
>   
> --- Raft is turned off by default.
> -assert(not box.cfg.raft_is_enabled)
> +-- Leadership is turned off by default.
> +assert(not box.cfg.leadership_is_enabled)
>    | ---
>    | - true
>    | ...
> --- Is candidate by default. Although it does not matter, until Raft is
> +-- Is candidate by default. Although it does not matter, until leadership is
>   -- turned on.
> -assert(box.cfg.raft_is_candidate)
> +assert(box.cfg.leadership_is_candidate)
>    | ---
>    | - true
>    | ...
> --- Ensure raft options are validated.
> -box.cfg{raft_is_enabled = 100}
> +-- Ensure leadership options are validated.
> +box.cfg{leadership_is_enabled = 100}
>    | ---
> - | - error: 'Incorrect value for option ''raft_is_enabled'': should be of type boolean'
> + | - error: 'Incorrect value for option ''leadership_is_enabled'': should be of type
> + |     boolean'
>    | ...
> -box.cfg{raft_is_candidate = 100}
> +box.cfg{leadership_is_candidate = 100}
>    | ---
> - | - error: 'Incorrect value for option ''raft_is_candidate'': should be of type boolean'
> + | - error: 'Incorrect value for option ''leadership_is_candidate'': should be of type
> + |     boolean'
>    | ...
> -box.cfg{raft_election_timeout = -1}
> +box.cfg{leadership_election_timeout = -1}
>    | ---
> - | - error: 'Incorrect value for option ''raft_election_timeout'': the value must be
> - |     a positive number'
> + | - error: 'Incorrect value for option ''leadership_election_timeout'': the value must
> + |     be a positive number'
>    | ...
> -box.cfg{raft_election_timeout = 0}
> +box.cfg{leadership_election_timeout = 0}
>    | ---
> - | - error: 'Incorrect value for option ''raft_election_timeout'': the value must be
> - |     a positive number'
> + | - error: 'Incorrect value for option ''leadership_election_timeout'': the value must
> + |     be a positive number'
>    | ...
>   
> --- When Raft is disabled, the instance is a follower. Does not
> --- try to become a leader, and does not block write operations.
> -term = box.info.raft.term
> +-- When leadership is disabled, the instance is a follower. Does not try to
> +-- become a leader, and does not block write operations.
> +term = box.info.leadership.term
>    | ---
>    | ...
> -vote = box.info.raft.vote
> +vote = box.info.leadership.vote
>    | ---
>    | ...
> -assert(box.info.raft.state == 'follower')
> +assert(box.info.leadership.state == 'follower')
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.leader == 0)
> +assert(box.info.leadership.leader == 0)
>    | ---
>    | - true
>    | ...
> @@ -62,15 +64,14 @@ assert(not box.info.ro)
>    | - true
>    | ...
>   
> --- Turned on Raft blocks writes until the instance becomes a
> --- leader.
> -box.cfg{raft_is_candidate = false}
> +-- Turned on leadership blocks writes until the instance becomes a leader.
> +box.cfg{leadership_is_candidate = false}
>    | ---
>    | ...
> -box.cfg{raft_is_enabled = true}
> +box.cfg{leadership_is_enabled = true}
>    | ---
>    | ...
> -assert(box.info.raft.state == 'follower')
> +assert(box.info.leadership.state == 'follower')
>    | ---
>    | - true
>    | ...
> @@ -80,55 +81,55 @@ assert(box.info.ro)
>    | ...
>   -- Term is not changed, because the instance can't be a candidate,
>   -- and therefore didn't try to vote nor to bump the term.
> -assert(box.info.raft.term == term)
> +assert(box.info.leadership.term == term)
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.vote == vote)
> +assert(box.info.leadership.vote == vote)
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.leader == 0)
> +assert(box.info.leadership.leader == 0)
>    | ---
>    | - true
>    | ...
>   
>   -- Candidate instance votes immediately, if sees no leader.
> -box.cfg{raft_election_timeout = 1000}
> +box.cfg{leadership_election_timeout = 1000}
>    | ---
>    | ...
> -box.cfg{raft_is_candidate = true}
> +box.cfg{leadership_is_candidate = true}
>    | ---
>    | ...
> -test_run:wait_cond(function() return box.info.raft.state == 'leader' end)
> +test_run:wait_cond(function() return box.info.leadership.state == 'leader' end)
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.term > term)
> +assert(box.info.leadership.term > term)
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.vote == box.info.id)
> +assert(box.info.leadership.vote == box.info.id)
>    | ---
>    | - true
>    | ...
> -assert(box.info.raft.leader == box.info.id)
> +assert(box.info.leadership.leader == box.info.id)
>    | ---
>    | - true
>    | ...
>   
>   box.cfg{                                                                        \
> -    raft_is_enabled = false,                                                    \
> -    raft_is_candidate = true,                                                   \
> -    raft_election_timeout = old_raft_election_timeout                           \
> +    leadership_is_enabled = false,                                              \
> +    leadership_is_candidate = true,                                             \
> +    leadership_election_timeout = old_leadership_election_timeout               \
>   }
>    | ---
>    | ...
>   
>   --
> --- See if bootstrap with Raft enabled works.
> +-- See if bootstrap with leadership enabled works.
>   --
> -SERVERS = {'raft_replica1', 'raft_replica2', 'raft_replica3'}
> +SERVERS = {'leadership_replica1', 'leadership_replica2', 'leadership_replica3'}
>    | ---
>    | ...
>   test_run:create_cluster(SERVERS, "replication")
> @@ -137,19 +138,19 @@ test_run:create_cluster(SERVERS, "replication")
>   test_run:wait_fullmesh(SERVERS)
>    | ---
>    | ...
> -is_leader_cmd = 'return box.info.raft.state == \'leader\''
> +is_leader_cmd = 'return box.info.leadership.state == \'leader\''
>    | ---
>    | ...
> -leader_id_cmd = 'return box.info.raft.leader'
> +leader_id_cmd = 'return box.info.leadership.leader'
>    | ---
>    | ...
> -is_r1_leader = test_run:eval('raft_replica1', is_leader_cmd)[1]
> +is_r1_leader = test_run:eval('leadership_replica1', is_leader_cmd)[1]
>    | ---
>    | ...
> -is_r2_leader = test_run:eval('raft_replica2', is_leader_cmd)[1]
> +is_r2_leader = test_run:eval('leadership_replica2', is_leader_cmd)[1]
>    | ---
>    | ...
> -is_r3_leader = test_run:eval('raft_replica3', is_leader_cmd)[1]
> +is_r3_leader = test_run:eval('leadership_replica3', is_leader_cmd)[1]
>    | ---
>    | ...
>   leader_count = is_r1_leader and 1 or 0
> @@ -166,13 +167,13 @@ assert(leader_count == 1)
>    | - true
>    | ...
>   -- All nodes have the same leader.
> -r1_leader = test_run:eval('raft_replica1', leader_id_cmd)[1]
> +r1_leader = test_run:eval('leadership_replica1', leader_id_cmd)[1]
>    | ---
>    | ...
> -r2_leader = test_run:eval('raft_replica2', leader_id_cmd)[1]
> +r2_leader = test_run:eval('leadership_replica2', leader_id_cmd)[1]
>    | ---
>    | ...
> -r3_leader = test_run:eval('raft_replica3', leader_id_cmd)[1]
> +r3_leader = test_run:eval('leadership_replica3', leader_id_cmd)[1]
>    | ---
>    | ...
>   assert(r1_leader ~= 0)
> @@ -201,17 +202,17 @@ nonleader2_name = nil
>    | ---
>    | ...
>   if is_r1_leader then                                                            \
> -    leader_name = 'raft_replica1'                                               \
> -    nonleader1_name = 'raft_replica2'                                           \
> -    nonleader2_name = 'raft_replica3'                                           \
> +    leader_name = 'leadership_replica1'                                         \
> +    nonleader1_name = 'leadership_replica2'                                     \
> +    nonleader2_name = 'leadership_replica3'                                     \
>   elseif is_r2_leader then                                                        \
> -    leader_name = 'raft_replica2'                                               \
> -    nonleader1_name = 'raft_replica1'                                           \
> -    nonleader2_name = 'raft_replica3'                                           \
> +    leader_name = 'leadership_replica2'                                         \
> +    nonleader1_name = 'leadership_replica1'                                     \
> +    nonleader2_name = 'leadership_replica3'                                     \
>   else                                                                            \
> -    leader_name = 'raft_replica3'                                               \
> -    nonleader1_name = 'raft_replica1'                                           \
> -    nonleader2_name = 'raft_replica2'                                           \
> +    leader_name = 'leadership_replica3'                                         \
> +    nonleader1_name = 'leadership_replica1'                                     \
> +    nonleader2_name = 'leadership_replica2'                                     \
>   end
>    | ---
>    | ...
> diff --git a/test/replication/leadership_basic.test.lua b/test/replication/leadership_basic.test.lua
> new file mode 100644
> index 000000000..f60459206
> --- /dev/null
> +++ b/test/replication/leadership_basic.test.lua
> @@ -0,0 +1,117 @@
> +test_run = require('test_run').new()
> +--
> +-- gh-1146: Raft protocol for automated leader election.
> +--
> +
> +old_leadership_election_timeout = box.cfg.leadership_election_timeout
> +
> +-- Leadership is turned off by default.
> +assert(not box.cfg.leadership_is_enabled)
> +-- Is candidate by default. Although it does not matter, until leadership is
> +-- turned on.
> +assert(box.cfg.leadership_is_candidate)
> +-- Ensure leadership options are validated.
> +box.cfg{leadership_is_enabled = 100}
> +box.cfg{leadership_is_candidate = 100}
> +box.cfg{leadership_election_timeout = -1}
> +box.cfg{leadership_election_timeout = 0}
> +
> +-- When leadership is disabled, the instance is a follower. Does not try to
> +-- become a leader, and does not block write operations.
> +term = box.info.leadership.term
> +vote = box.info.leadership.vote
> +assert(box.info.leadership.state == 'follower')
> +assert(box.info.leadership.leader == 0)
> +assert(not box.info.ro)
> +
> +-- Turned on leadership blocks writes until the instance becomes a leader.
> +box.cfg{leadership_is_candidate = false}
> +box.cfg{leadership_is_enabled = true}
> +assert(box.info.leadership.state == 'follower')
> +assert(box.info.ro)
> +-- Term is not changed, because the instance can't be a candidate,
> +-- and therefore didn't try to vote nor to bump the term.
> +assert(box.info.leadership.term == term)
> +assert(box.info.leadership.vote == vote)
> +assert(box.info.leadership.leader == 0)
> +
> +-- Candidate instance votes immediately, if sees no leader.
> +box.cfg{leadership_election_timeout = 1000}
> +box.cfg{leadership_is_candidate = true}
> +test_run:wait_cond(function() return box.info.leadership.state == 'leader' end)
> +assert(box.info.leadership.term > term)
> +assert(box.info.leadership.vote == box.info.id)
> +assert(box.info.leadership.leader == box.info.id)
> +
> +box.cfg{                                                                        \
> +    leadership_is_enabled = false,                                              \
> +    leadership_is_candidate = true,                                             \
> +    leadership_election_timeout = old_leadership_election_timeout               \
> +}
> +
> +--
> +-- See if bootstrap with leadership enabled works.
> +--
> +SERVERS = {'leadership_replica1', 'leadership_replica2', 'leadership_replica3'}
> +test_run:create_cluster(SERVERS, "replication")
> +test_run:wait_fullmesh(SERVERS)
> +is_leader_cmd = 'return box.info.leadership.state == \'leader\''
> +leader_id_cmd = 'return box.info.leadership.leader'
> +is_r1_leader = test_run:eval('leadership_replica1', is_leader_cmd)[1]
> +is_r2_leader = test_run:eval('leadership_replica2', is_leader_cmd)[1]
> +is_r3_leader = test_run:eval('leadership_replica3', is_leader_cmd)[1]
> +leader_count = is_r1_leader and 1 or 0
> +leader_count = leader_count + (is_r2_leader and 1 or 0)
> +leader_count = leader_count + (is_r3_leader and 1 or 0)
> +assert(leader_count == 1)
> +-- All nodes have the same leader.
> +r1_leader = test_run:eval('leadership_replica1', leader_id_cmd)[1]
> +r2_leader = test_run:eval('leadership_replica2', leader_id_cmd)[1]
> +r3_leader = test_run:eval('leadership_replica3', leader_id_cmd)[1]
> +assert(r1_leader ~= 0)
> +assert(r1_leader == r2_leader)
> +assert(r1_leader == r3_leader)
> +
> +--
> +-- Leader death starts a new election.
> +--
> +leader_name = nil
> +nonleader1_name = nil
> +nonleader2_name = nil
> +if is_r1_leader then                                                            \
> +    leader_name = 'leadership_replica1'                                         \
> +    nonleader1_name = 'leadership_replica2'                                     \
> +    nonleader2_name = 'leadership_replica3'                                     \
> +elseif is_r2_leader then                                                        \
> +    leader_name = 'leadership_replica2'                                         \
> +    nonleader1_name = 'leadership_replica1'                                     \
> +    nonleader2_name = 'leadership_replica3'                                     \
> +else                                                                            \
> +    leader_name = 'leadership_replica3'                                         \
> +    nonleader1_name = 'leadership_replica1'                                     \
> +    nonleader2_name = 'leadership_replica2'                                     \
> +end
> +-- Lower the quorum so the 2 alive nodes could elect a new leader when the third
> +-- node dies.
> +test_run:switch(nonleader1_name)
> +box.cfg{replication_synchro_quorum = 2}
> +-- Switch via default where the names are defined.
> +test_run:switch('default')
> +test_run:switch(nonleader2_name)
> +box.cfg{replication_synchro_quorum = 2}
> +
> +test_run:switch('default')
> +test_run:cmd(string.format('stop server %s', leader_name))
> +test_run:wait_cond(function()                                                   \
> +    is_r1_leader = test_run:eval(nonleader1_name, is_leader_cmd)[1]             \
> +    is_r2_leader = test_run:eval(nonleader2_name, is_leader_cmd)[1]             \
> +    return is_r1_leader or is_r2_leader                                         \
> +end)
> +r1_leader = test_run:eval(nonleader1_name, leader_id_cmd)[1]
> +r2_leader = test_run:eval(nonleader2_name, leader_id_cmd)[1]
> +assert(r1_leader ~= 0)
> +assert(r1_leader == r2_leader)
> +
> +test_run:cmd(string.format('start server %s', leader_name))
> +
> +test_run:drop_cluster(SERVERS)
> diff --git a/test/replication/raft_replica.lua b/test/replication/leadership_replica.lua
> similarity index 80%
> rename from test/replication/raft_replica.lua
> rename to test/replication/leadership_replica.lua
> index 8b4c740d8..b1444ecec 100644
> --- a/test/replication/raft_replica.lua
> +++ b/test/replication/leadership_replica.lua
> @@ -17,11 +17,11 @@ box.cfg({
>           instance_uri(3),
>       },
>       replication_timeout = 0.1,
> -    raft_is_enabled = true,
> -    raft_is_candidate = true,
> -    raft_election_timeout = 0.1,
> +    leadership_is_enabled = true,
> +    leadership_is_candidate = true,
> +    leadership_election_timeout = 0.1,
>       replication_synchro_quorum = 3,
> -    -- To reveal more Raft logs.
> +    -- To reveal more leadership logs.
>       log_level = 6,
>   })
>   
> diff --git a/test/replication/leadership_replica1.lua b/test/replication/leadership_replica1.lua
> new file mode 120000
> index 000000000..e81800b8c
> --- /dev/null
> +++ b/test/replication/leadership_replica1.lua
> @@ -0,0 +1 @@
> +leadership_replica.lua
> \ No newline at end of file
> diff --git a/test/replication/leadership_replica2.lua b/test/replication/leadership_replica2.lua
> new file mode 120000
> index 000000000..e81800b8c
> --- /dev/null
> +++ b/test/replication/leadership_replica2.lua
> @@ -0,0 +1 @@
> +leadership_replica.lua
> \ No newline at end of file
> diff --git a/test/replication/leadership_replica3.lua b/test/replication/leadership_replica3.lua
> new file mode 120000
> index 000000000..e81800b8c
> --- /dev/null
> +++ b/test/replication/leadership_replica3.lua
> @@ -0,0 +1 @@
> +leadership_replica.lua
> \ No newline at end of file
> diff --git a/test/replication/raft_basic.test.lua b/test/replication/raft_basic.test.lua
> deleted file mode 100644
> index b8e5a5eaf..000000000
> --- a/test/replication/raft_basic.test.lua
> +++ /dev/null
> @@ -1,118 +0,0 @@
> -test_run = require('test_run').new()
> ---
> --- gh-1146: Raft protocol for automated leader election.
> ---
> -
> -old_raft_election_timeout = box.cfg.raft_election_timeout
> -
> --- Raft is turned off by default.
> -assert(not box.cfg.raft_is_enabled)
> --- Is candidate by default. Although it does not matter, until Raft is
> --- turned on.
> -assert(box.cfg.raft_is_candidate)
> --- Ensure raft options are validated.
> -box.cfg{raft_is_enabled = 100}
> -box.cfg{raft_is_candidate = 100}
> -box.cfg{raft_election_timeout = -1}
> -box.cfg{raft_election_timeout = 0}
> -
> --- When Raft is disabled, the instance is a follower. Does not
> --- try to become a leader, and does not block write operations.
> -term = box.info.raft.term
> -vote = box.info.raft.vote
> -assert(box.info.raft.state == 'follower')
> -assert(box.info.raft.leader == 0)
> -assert(not box.info.ro)
> -
> --- Turned on Raft blocks writes until the instance becomes a
> --- leader.
> -box.cfg{raft_is_candidate = false}
> -box.cfg{raft_is_enabled = true}
> -assert(box.info.raft.state == 'follower')
> -assert(box.info.ro)
> --- Term is not changed, because the instance can't be a candidate,
> --- and therefore didn't try to vote nor to bump the term.
> -assert(box.info.raft.term == term)
> -assert(box.info.raft.vote == vote)
> -assert(box.info.raft.leader == 0)
> -
> --- Candidate instance votes immediately, if sees no leader.
> -box.cfg{raft_election_timeout = 1000}
> -box.cfg{raft_is_candidate = true}
> -test_run:wait_cond(function() return box.info.raft.state == 'leader' end)
> -assert(box.info.raft.term > term)
> -assert(box.info.raft.vote == box.info.id)
> -assert(box.info.raft.leader == box.info.id)
> -
> -box.cfg{                                                                        \
> -    raft_is_enabled = false,                                                    \
> -    raft_is_candidate = true,                                                   \
> -    raft_election_timeout = old_raft_election_timeout                           \
> -}
> -
> ---
> --- See if bootstrap with Raft enabled works.
> ---
> -SERVERS = {'raft_replica1', 'raft_replica2', 'raft_replica3'}
> -test_run:create_cluster(SERVERS, "replication")
> -test_run:wait_fullmesh(SERVERS)
> -is_leader_cmd = 'return box.info.raft.state == \'leader\''
> -leader_id_cmd = 'return box.info.raft.leader'
> -is_r1_leader = test_run:eval('raft_replica1', is_leader_cmd)[1]
> -is_r2_leader = test_run:eval('raft_replica2', is_leader_cmd)[1]
> -is_r3_leader = test_run:eval('raft_replica3', is_leader_cmd)[1]
> -leader_count = is_r1_leader and 1 or 0
> -leader_count = leader_count + (is_r2_leader and 1 or 0)
> -leader_count = leader_count + (is_r3_leader and 1 or 0)
> -assert(leader_count == 1)
> --- All nodes have the same leader.
> -r1_leader = test_run:eval('raft_replica1', leader_id_cmd)[1]
> -r2_leader = test_run:eval('raft_replica2', leader_id_cmd)[1]
> -r3_leader = test_run:eval('raft_replica3', leader_id_cmd)[1]
> -assert(r1_leader ~= 0)
> -assert(r1_leader == r2_leader)
> -assert(r1_leader == r3_leader)
> -
> ---
> --- Leader death starts a new election.
> ---
> -leader_name = nil
> -nonleader1_name = nil
> -nonleader2_name = nil
> -if is_r1_leader then                                                            \
> -    leader_name = 'raft_replica1'                                               \
> -    nonleader1_name = 'raft_replica2'                                           \
> -    nonleader2_name = 'raft_replica3'                                           \
> -elseif is_r2_leader then                                                        \
> -    leader_name = 'raft_replica2'                                               \
> -    nonleader1_name = 'raft_replica1'                                           \
> -    nonleader2_name = 'raft_replica3'                                           \
> -else                                                                            \
> -    leader_name = 'raft_replica3'                                               \
> -    nonleader1_name = 'raft_replica1'                                           \
> -    nonleader2_name = 'raft_replica2'                                           \
> -end
> --- Lower the quorum so the 2 alive nodes could elect a new leader when the third
> --- node dies.
> -test_run:switch(nonleader1_name)
> -box.cfg{replication_synchro_quorum = 2}
> --- Switch via default where the names are defined.
> -test_run:switch('default')
> -test_run:switch(nonleader2_name)
> -box.cfg{replication_synchro_quorum = 2}
> -
> -test_run:switch('default')
> -test_run:cmd(string.format('stop server %s', leader_name))
> -test_run:wait_cond(function()                                                   \
> -    is_r1_leader = test_run:eval(nonleader1_name, is_leader_cmd)[1]             \
> -    is_r2_leader = test_run:eval(nonleader2_name, is_leader_cmd)[1]             \
> -    return is_r1_leader or is_r2_leader                                         \
> -end)
> -r1_leader = test_run:eval(nonleader1_name, leader_id_cmd)[1]
> -r2_leader = test_run:eval(nonleader2_name, leader_id_cmd)[1]
> -assert(r1_leader ~= 0)
> -assert(r1_leader == r2_leader)
> -
> -test_run:cmd(string.format('start server %s', leader_name))
> -
> -test_run:drop_cluster(SERVERS)
> diff --git a/test/replication/raft_replica1.lua b/test/replication/raft_replica1.lua
> deleted file mode 120000
> index d1f4d6f25..000000000
> --- a/test/replication/raft_replica1.lua
> +++ /dev/null
> @@ -1 +0,0 @@
> -raft_replica.lua
> \ No newline at end of file
> diff --git a/test/replication/raft_replica2.lua b/test/replication/raft_replica2.lua
> deleted file mode 120000
> index d1f4d6f25..000000000
> --- a/test/replication/raft_replica2.lua
> +++ /dev/null
> @@ -1 +0,0 @@
> -raft_replica.lua
> \ No newline at end of file
> diff --git a/test/replication/raft_replica3.lua b/test/replication/raft_replica3.lua
> deleted file mode 120000
> index d1f4d6f25..000000000
> --- a/test/replication/raft_replica3.lua
> +++ /dev/null
> @@ -1 +0,0 @@
> -raft_replica.lua
> \ No newline at end of file

-- 
Serge Petrenko



More information about the Tarantool-patches mailing list