From: Serge Petrenko <sergepetrenko@tarantool.org>
To: v.shpilevoy@tarantool.org
Cc: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH] raft: add a test with synchronous replication
Date: Fri, 2 Oct 2020 13:33:12 +0300 [thread overview]
Message-ID: <20201002103312.23042-1-sergepetrenko@tarantool.org> (raw)
---
Branch: https://github.com/tarantool/tarantool/tree/sp/raft-qsync-test
The test is relatively long (runs for 10 seconds on my machine).
but I still think it's worth having it, at least under --long option (I haven't
added it to long_run list yet).
test/replication/election_qsync.result | 125 +++++++++++++++++++++++
test/replication/election_qsync.test.lua | 70 +++++++++++++
test/replication/election_replica.lua | 10 +-
3 files changed, 202 insertions(+), 3 deletions(-)
create mode 100644 test/replication/election_qsync.result
create mode 100644 test/replication/election_qsync.test.lua
diff --git a/test/replication/election_qsync.result b/test/replication/election_qsync.result
new file mode 100644
index 000000000..1bf13d7bc
--- /dev/null
+++ b/test/replication/election_qsync.result
@@ -0,0 +1,125 @@
+-- test-run result file version 2
+test_run = require('test_run').new()
+ | ---
+ | ...
+netbox = require('net.box')
+ | ---
+ | ...
+
+--
+-- gh-1146: Leader election + Qsync
+--
+test_run:cmd('setopt delimiter ";"')
+ | ---
+ | - true
+ | ...
+function get_leader(nrs)
+ local is_leader_cmd = 'return box.info.election.state == \'leader\''
+ local leader_nr = 0
+ test_run:wait_cond(function()
+ local leader_count = 0
+ for nr, do_check in pairs(nrs) do
+ if do_check then
+ local is_leader = test_run:eval('election_replica'..nr,
+ is_leader_cmd)[1]
+ if is_leader then
+ leader_count = leader_count + 1
+ leader_nr = nr
+ end
+ assert(leader_count <= 1)
+ end
+ end
+ return leader_count == 1
+ end)
+ return leader_nr
+end;
+ | ---
+ | ...
+
+test_run:cmd('setopt delimiter ""');
+ | ---
+ | - true
+ | ...
+
+SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'}
+ | ---
+ | ...
+test_run:create_cluster(SERVERS, "replication", {args='2'})
+ | ---
+ | ...
+test_run:wait_fullmesh(SERVERS)
+ | ---
+ | ...
+
+nrs = {true, true, true}
+ | ---
+ | ...
+old_leader_nr = get_leader(nrs)
+ | ---
+ | ...
+old_leader = 'election_replica'..old_leader_nr
+ | ---
+ | ...
+leader_port = test_run:eval(old_leader, 'box.cfg.listen')[1]
+ | ---
+ | ...
+c = netbox.connect(leader_port)
+ | ---
+ | ...
+
+_ = c:eval('box.schema.space.create("test", {is_sync=true})')
+ | ---
+ | ...
+_ = c:eval('box.space.test:create_index("pk")')
+ | ---
+ | ...
+
+-- Insert some data to a synchronous space, then kill the leader before the
+-- confirmation is written. Check successful confirmation on the new leader.
+test_run:cmd('setopt delimiter ";"')
+ | ---
+ | - true
+ | ...
+for i = 1,10 do
+ c:eval('box.cfg{replication_synchro_quorum=4, replication_synchro_timeout=1000}')
+ c.space.test:insert({i}, {is_async=true})
+ test_run:wait_cond(function() return c.space.test:get{i} ~= nil end)
+ test_run:cmd('stop server '..old_leader)
+ nrs[old_leader_nr] = false
+ new_leader_nr = get_leader(nrs)
+ new_leader = 'election_replica'..new_leader_nr
+ leader_port = test_run:eval(new_leader, 'box.cfg.listen')[1]
+ c = netbox.connect(leader_port)
+ c:eval('box.ctl.clear_synchro_queue()')
+ c:eval('box.cfg{replication_synchro_timeout=1000}')
+ c.space._schema:replace{'smth'}
+ c.space.test:get{i}
+ test_run:cmd('start server '..old_leader..' with wait=True, wait_load=True, args="2"')
+ nrs[old_leader_nr] = true
+ old_leader_nr = new_leader_nr
+ old_leader = new_leader
+end;
+ | ---
+ | ...
+test_run:cmd('setopt delimiter ""');
+ | ---
+ | - true
+ | ...
+-- We're connected to some leader.
+c.space.test:select{}
+ | ---
+ | - - [1]
+ | - [2]
+ | - [3]
+ | - [4]
+ | - [5]
+ | - [6]
+ | - [7]
+ | - [8]
+ | - [9]
+ | - [10]
+ | ...
+
+test_run:drop_cluster(SERVERS)
+ | ---
+ | ...
diff --git a/test/replication/election_qsync.test.lua b/test/replication/election_qsync.test.lua
new file mode 100644
index 000000000..f069c71bb
--- /dev/null
+++ b/test/replication/election_qsync.test.lua
@@ -0,0 +1,70 @@
+test_run = require('test_run').new()
+netbox = require('net.box')
+
+--
+-- gh-1146: Leader election + Qsync
+--
+test_run:cmd('setopt delimiter ";"')
+function get_leader(nrs)
+ local is_leader_cmd = 'return box.info.election.state == \'leader\''
+ local leader_nr = 0
+ test_run:wait_cond(function()
+ local leader_count = 0
+ for nr, do_check in pairs(nrs) do
+ if do_check then
+ local is_leader = test_run:eval('election_replica'..nr,
+ is_leader_cmd)[1]
+ if is_leader then
+ leader_count = leader_count + 1
+ leader_nr = nr
+ end
+ assert(leader_count <= 1)
+ end
+ end
+ return leader_count == 1
+ end)
+ return leader_nr
+end;
+
+test_run:cmd('setopt delimiter ""');
+
+SERVERS = {'election_replica1', 'election_replica2', 'election_replica3'}
+test_run:create_cluster(SERVERS, "replication", {args='2'})
+test_run:wait_fullmesh(SERVERS)
+
+nrs = {true, true, true}
+old_leader_nr = get_leader(nrs)
+old_leader = 'election_replica'..old_leader_nr
+leader_port = test_run:eval(old_leader, 'box.cfg.listen')[1]
+c = netbox.connect(leader_port)
+
+_ = c:eval('box.schema.space.create("test", {is_sync=true})')
+_ = c:eval('box.space.test:create_index("pk")')
+
+-- Insert some data to a synchronous space, then kill the leader before the
+-- confirmation is written. Check successful confirmation on the new leader.
+test_run:cmd('setopt delimiter ";"')
+for i = 1,10 do
+ c:eval('box.cfg{replication_synchro_quorum=4, replication_synchro_timeout=1000}')
+ c.space.test:insert({i}, {is_async=true})
+ test_run:wait_cond(function() return c.space.test:get{i} ~= nil end)
+ test_run:cmd('stop server '..old_leader)
+ nrs[old_leader_nr] = false
+ new_leader_nr = get_leader(nrs)
+ new_leader = 'election_replica'..new_leader_nr
+ leader_port = test_run:eval(new_leader, 'box.cfg.listen')[1]
+ c = netbox.connect(leader_port)
+ c:eval('box.ctl.clear_synchro_queue()')
+ c:eval('box.cfg{replication_synchro_timeout=1000}')
+ c.space._schema:replace{'smth'}
+ c.space.test:get{i}
+ test_run:cmd('start server '..old_leader..' with wait=True, wait_load=True, args="2"')
+ nrs[old_leader_nr] = true
+ old_leader_nr = new_leader_nr
+ old_leader = new_leader
+end;
+test_run:cmd('setopt delimiter ""');
+-- We're connected to some leader.
+c.space.test:select{}
+
+test_run:drop_cluster(SERVERS)
diff --git a/test/replication/election_replica.lua b/test/replication/election_replica.lua
index 36ea1f077..887d8a2a0 100644
--- a/test/replication/election_replica.lua
+++ b/test/replication/election_replica.lua
@@ -2,9 +2,10 @@
local INSTANCE_ID = string.match(arg[0], "%d")
local SOCKET_DIR = require('fio').cwd()
+local SYNCHRO_QUORUM = arg[1] and tonumber(arg[1]) or 3
local function instance_uri(instance_id)
- return SOCKET_DIR..'/autobootstrap'..instance_id..'.sock';
+ return SOCKET_DIR..'/election_replica'..instance_id..'.sock';
end
require('console').listen(os.getenv('ADMIN'))
@@ -19,8 +20,11 @@ box.cfg({
replication_timeout = 0.1,
election_is_enabled = true,
election_is_candidate = true,
- election_timeout = 0.1,
- replication_synchro_quorum = 3,
+ -- Should be at least as big as replication_disconnect_timeout, which is
+ -- 4 * replication_timeout.
+ election_timeout = 0.4,
+ replication_synchro_quorum = SYNCHRO_QUORUM,
+ replication_synchro_timeout = 0.1,
-- To reveal more election logs.
log_level = 6,
})
--
2.24.3 (Apple Git-128)
next reply other threads:[~2020-10-02 10:33 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-02 10:33 Serge Petrenko [this message]
2020-10-04 13:54 ` Vladislav Shpilevoy
2020-10-05 8:52 ` Serge Petrenko
2020-10-05 21:40 ` Vladislav Shpilevoy
2020-10-06 7:30 ` Serge Petrenko
2020-10-06 10:04 ` Kirill Yukhin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201002103312.23042-1-sergepetrenko@tarantool.org \
--to=sergepetrenko@tarantool.org \
--cc=tarantool-patches@dev.tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH] raft: add a test with synchronous replication' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox