[Tarantool-patches] [PATCH v4 13/16] box: allow calling promote on a candidate

Serge Petrenko sergepetrenko at tarantool.org
Wed Jul 14 21:25:41 MSK 2021


Part of #6034
---
 src/box/box.cc                                | 15 +---
 .../gh-6034-election-candidate-promote.result | 84 +++++++++++++++++++
 ...h-6034-election-candidate-promote.test.lua | 42 ++++++++++
 test/replication/suite.cfg                    |  1 +
 4 files changed, 128 insertions(+), 14 deletions(-)
 create mode 100644 test/replication/gh-6034-election-candidate-promote.result
 create mode 100644 test/replication/gh-6034-election-candidate-promote.test.lua

diff --git a/src/box/box.cc b/src/box/box.cc
index 6a534952f..9130fc322 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -1717,21 +1717,8 @@ box_promote(void)
 			 "manual elections");
 		return -1;
 	case ELECTION_MODE_MANUAL:
-		if (box_raft()->state == RAFT_STATE_LEADER)
-			return 0;
-		run_elections = true;
-		break;
 	case ELECTION_MODE_CANDIDATE:
-		/*
-		 * Leader elections are enabled, and this instance is allowed to
-		 * promote only if it's already an elected leader. No manual
-		 * elections.
-		 */
-		if (box_raft()->state != RAFT_STATE_LEADER) {
-			diag_set(ClientError, ER_UNSUPPORTED, "election_mode="
-				 "'candidate'", "manual elections");
-			return -1;
-		}
+		run_elections = box_raft()->state != RAFT_STATE_LEADER;
 		break;
 	default:
 		unreachable();
diff --git a/test/replication/gh-6034-election-candidate-promote.result b/test/replication/gh-6034-election-candidate-promote.result
new file mode 100644
index 000000000..76a54d5a6
--- /dev/null
+++ b/test/replication/gh-6034-election-candidate-promote.result
@@ -0,0 +1,84 @@
+-- test-run result file version 2
+test_run = require('test_run').new()
+ | ---
+ | ...
+
+SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'}
+ | ---
+ | ...
+test_run:create_cluster(SERVERS, 'replication')
+ | ---
+ | ...
+test_run:wait_fullmesh(SERVERS)
+ | ---
+ | ...
+is_leader_cmd = 'return box.info.election.state == \'leader\''
+ | ---
+ | ...
+
+test_run:cmd("setopt delimiter ';'")
+ | ---
+ | - true
+ | ...
+function get_leader_nr()
+    local leader_nr = 0
+    test_run:wait_cond(function()
+        for nr = 1,3 do
+            local is_leader = test_run:eval('election_replica'..nr, is_leader_cmd)[1]
+            if is_leader then
+                leader_nr = nr
+                return true
+            end
+        end
+        return false
+    end)
+    return leader_nr
+end;
+ | ---
+ | ...
+test_run:cmd("setopt delimiter ''");
+ | ---
+ | - true
+ | ...
+
+leader_nr = get_leader_nr()
+ | ---
+ | ...
+
+assert(leader_nr ~= 0)
+ | ---
+ | - true
+ | ...
+
+term = test_run:eval('election_replica'..leader_nr,\
+                     'return box.info.election.term')[1]
+ | ---
+ | ...
+
+next_nr = leader_nr % 3 + 1
+ | ---
+ | ...
+-- Someone else may become a leader, thus promote may fail. But we're testing
+-- that it takes effect at all, so that's fine.
+_ = pcall(test_run:eval('election_replica'..next_nr, 'box.ctl.promote()'))
+ | ---
+ | ...
+new_term = test_run:eval('election_replica'..next_nr,\
+                         'return box.info.election.term')[1]
+ | ---
+ | ...
+assert(new_term > term)
+ | ---
+ | - true
+ | ...
+leader_nr = get_leader_nr()
+ | ---
+ | ...
+assert(leader_nr ~= 0)
+ | ---
+ | - true
+ | ...
+
+test_run:drop_cluster(SERVERS)
+ | ---
+ | ...
diff --git a/test/replication/gh-6034-election-candidate-promote.test.lua b/test/replication/gh-6034-election-candidate-promote.test.lua
new file mode 100644
index 000000000..24c57f4cb
--- /dev/null
+++ b/test/replication/gh-6034-election-candidate-promote.test.lua
@@ -0,0 +1,42 @@
+test_run = require('test_run').new()
+
+SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'}
+test_run:create_cluster(SERVERS, 'replication')
+test_run:wait_fullmesh(SERVERS)
+is_leader_cmd = 'return box.info.election.state == \'leader\''
+
+test_run:cmd("setopt delimiter ';'")
+function get_leader_nr()
+    local leader_nr = 0
+    test_run:wait_cond(function()
+        for nr = 1,3 do
+            local is_leader = test_run:eval('election_replica'..nr, is_leader_cmd)[1]
+            if is_leader then
+                leader_nr = nr
+                return true
+            end
+        end
+        return false
+    end)
+    return leader_nr
+end;
+test_run:cmd("setopt delimiter ''");
+
+leader_nr = get_leader_nr()
+
+assert(leader_nr ~= 0)
+
+term = test_run:eval('election_replica'..leader_nr,\
+                     'return box.info.election.term')[1]
+
+next_nr = leader_nr % 3 + 1
+-- Someone else may become a leader, thus promote may fail. But we're testing
+-- that it takes effect at all, so that's fine.
+_ = pcall(test_run:eval('election_replica'..next_nr, 'box.ctl.promote()'))
+new_term = test_run:eval('election_replica'..next_nr,\
+                         'return box.info.election.term')[1]
+assert(new_term > term)
+leader_nr = get_leader_nr()
+assert(leader_nr ~= 0)
+
+test_run:drop_cluster(SERVERS)
diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
index 8b2204e2a..6f42db081 100644
--- a/test/replication/suite.cfg
+++ b/test/replication/suite.cfg
@@ -53,6 +53,7 @@
     "gh-6057-qsync-confirm-async-no-wal.test.lua": {},
     "gh-6094-rs-uuid-mismatch.test.lua": {},
     "gh-6127-election-join-new.test.lua": {},
+    "gh-6034-election-candidate-promote.test.lua": {},
     "gh-6035-applier-filter.test.lua": {},
     "*": {
         "memtx": {"engine": "memtx"},
-- 
2.30.1 (Apple Git-130)



More information about the Tarantool-patches mailing list