Tarantool development patches archive
 help / color / mirror / Atom feed
* [Tarantool-patches] [PATCH] box: introduce on_election triggers
@ 2021-07-22  7:20 Serge Petrenko via Tarantool-patches
  2021-07-26 20:27 ` Vladislav Shpilevoy via Tarantool-patches
  0 siblings, 1 reply; 5+ messages in thread
From: Serge Petrenko via Tarantool-patches @ 2021-07-22  7:20 UTC (permalink / raw)
  To: v.shpilevoy, gorcunov; +Cc: tarantool-patches

On_election triggers are fired asynchronously after any Raft event with
a broadcast, they are run in a worker fiber, so it's allowed to yield
inside them, unlike Raft's on_update triggers we already had.

Closes #5819

@TarantoolBot document
Title: document triggers on election state change

A new function to register triggers is added, `box.ctl.on_election()`.
Triggers registered via this function are run asynchronously every time
a visible change in `box.info.election` table appears.
No parameters are passed to the trigger, it may check what's changed by
looking at `box.info.election` and `box.info.synchro`.
---
I'm not sure whether every change in `box.info.election.vote` actually runs the
triggers. That's because I run triggers inside of box_raft_broadcast(), which
isn't triggered on vote change. I thought of adding raft_schedule_trigger as a
counterpart to raft_schedule_broadcast. Then raft_sm_schedule_new_vote() would
have raft_schedule_trigger() instead of raft_schedule_broadcast(), and the
triggers would fire on a vote change as well.

https://github.com/tarantool/tarantool/issues/5819
https://github.com/tarantool/tarantool/tree/sp/gh-5819-raft-state-triggers

.../unreleased/gh-5819-election-triggers.md   |   5 +
 src/box/lua/ctl.c                             |   8 +
 src/box/raft.c                                |   3 +
 src/box/raft.h                                |   7 +
 .../gh-5819-election-triggers.result          | 147 ++++++++++++++++++
 .../gh-5819-election-triggers.test.lua        |  53 +++++++
 test/replication/suite.cfg                    |   1 +
 7 files changed, 224 insertions(+)
 create mode 100644 changelogs/unreleased/gh-5819-election-triggers.md
 create mode 100644 test/replication/gh-5819-election-triggers.result
 create mode 100644 test/replication/gh-5819-election-triggers.test.lua

diff --git a/changelogs/unreleased/gh-5819-election-triggers.md b/changelogs/unreleased/gh-5819-election-triggers.md
new file mode 100644
index 000000000..edb7be8ac
--- /dev/null
+++ b/changelogs/unreleased/gh-5819-election-triggers.md
@@ -0,0 +1,5 @@
+## feature/replication
+
+* Introduce on_election triggers. The triggers may be registered via
+`box.ctl.on_election()` interface and are run asynchronously each time
+`box.info.election` changes (gh-5819).
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 368b9ab60..4b2a467d8 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -43,6 +43,7 @@
 #include "box/schema.h"
 #include "box/engine.h"
 #include "box/memtx_engine.h"
+#include "box/raft.h"
 
 static int
 lbox_ctl_wait_ro(struct lua_State *L)
@@ -81,6 +82,12 @@ lbox_ctl_on_schema_init(struct lua_State *L)
 	return lbox_trigger_reset(L, 2, &on_schema_init, NULL, NULL);
 }
 
+static int
+lbox_ctl_on_election(struct lua_State *L)
+{
+	return lbox_trigger_reset(L, 2, &box_raft_on_state, NULL, NULL);
+}
+
 static int
 lbox_ctl_promote(struct lua_State *L)
 {
@@ -124,6 +131,7 @@ static const struct luaL_Reg lbox_ctl_lib[] = {
 	{"wait_rw", lbox_ctl_wait_rw},
 	{"on_shutdown", lbox_ctl_on_shutdown},
 	{"on_schema_init", lbox_ctl_on_schema_init},
+	{"on_election", lbox_ctl_on_election},
 	{"promote", lbox_ctl_promote},
 	/* An old alias. */
 	{"clear_synchro_queue", lbox_ctl_promote},
diff --git a/src/box/raft.c b/src/box/raft.c
index 7f787c0c5..c9c3ba818 100644
--- a/src/box/raft.c
+++ b/src/box/raft.c
@@ -52,6 +52,8 @@ enum election_mode box_election_mode = ELECTION_MODE_INVALID;
  */
 static struct trigger box_raft_on_update;
 
+struct rlist box_raft_on_state = RLIST_HEAD_INITIALIZER(box_raft_on_state);
+
 /**
  * Worker fiber does all the asynchronous work, which may need yields and can be
  * long. These are WAL writes, network broadcasts. That allows not to block the
@@ -274,6 +276,7 @@ box_raft_broadcast(struct raft *raft, const struct raft_msg *msg)
 	assert(raft == box_raft());
 	struct raft_request req;
 	box_raft_msg_to_request(msg, &req);
+	trigger_run(&box_raft_on_state, NULL);
 	replicaset_foreach(replica)
 		relay_push_raft(replica->relay, &req);
 }
diff --git a/src/box/raft.h b/src/box/raft.h
index 6b6136510..dbe16eebf 100644
--- a/src/box/raft.h
+++ b/src/box/raft.h
@@ -30,11 +30,18 @@
  * SUCH DAMAGE.
  */
 #include "raft/raft.h"
+#include "small/rlist.h"
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
+/**
+ * A public trigger fired on Raft state change. It's allowed to yield inside
+ * it, and it's run asynchronously.
+ */
+extern struct rlist box_raft_on_state;
+
 enum election_mode {
 	ELECTION_MODE_INVALID = -1,
 	ELECTION_MODE_OFF = 0,
diff --git a/test/replication/gh-5819-election-triggers.result b/test/replication/gh-5819-election-triggers.result
new file mode 100644
index 000000000..546aac8a2
--- /dev/null
+++ b/test/replication/gh-5819-election-triggers.result
@@ -0,0 +1,147 @@
+-- test-run result file version 2
+test_run = require('test_run').new()
+ | ---
+ | ...
+
+box.schema.user.grant('guest', 'replication')
+ | ---
+ | ...
+test_run:cmd('create server replica with rpl_master=default,\
+	      script="replication/replica.lua"')
+ | ---
+ | - true
+ | ...
+test_run:cmd('start server replica')
+ | ---
+ | - true
+ | ...
+
+repl = test_run:eval('replica', 'return box.cfg.listen')[1]
+ | ---
+ | ...
+box.cfg{replication = repl}
+ | ---
+ | ...
+test_run:switch('replica')
+ | ---
+ | - true
+ | ...
+box.cfg{election_mode='voter'}
+ | ---
+ | ...
+test_run:switch('default')
+ | ---
+ | - true
+ | ...
+
+election_tbl = {}
+ | ---
+ | ...
+
+function trig()\
+    election_tbl[#election_tbl+1] = box.info.election\
+end
+ | ---
+ | ...
+
+_ = box.ctl.on_election(trig)
+ | ---
+ | ...
+
+box.cfg{replication_synchro_quorum=2}
+ | ---
+ | ...
+box.cfg{election_mode='candidate'}
+ | ---
+ | ...
+
+test_run:wait_cond(function() return box.info.election.state == 'leader' end)
+ | ---
+ | - true
+ | ...
+assert(#election_tbl == 3)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[1].state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[2].state == 'candidate')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[2].vote == 1)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[3].state == 'leader')
+ | ---
+ | - true
+ | ...
+box.cfg{election_mode='voter'}
+ | ---
+ | ...
+
+assert(#election_tbl == 4)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[4].state == 'follower')
+ | ---
+ | - true
+ | ...
+
+box.cfg{election_mode='off'}
+ | ---
+ | ...
+assert(#election_tbl == 5)
+ | ---
+ | - true
+ | ...
+
+box.cfg{election_mode='manual'}
+ | ---
+ | ...
+
+assert(#election_tbl == 6)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[6].state == 'follower')
+ | ---
+ | - true
+ | ...
+
+box.ctl.promote()
+ | ---
+ | ...
+
+assert(#election_tbl == 9)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[7].state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[8].state == 'candidate')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[9].state == 'leader')
+ | ---
+ | - true
+ | ...
+
+test_run:cmd('stop server replica')
+ | ---
+ | - true
+ | ...
+test_run:cmd('delete server replica')
+ | ---
+ | - true
+ | ...
+box.schema.user.revoke('guest', 'replication')
+ | ---
+ | ...
diff --git a/test/replication/gh-5819-election-triggers.test.lua b/test/replication/gh-5819-election-triggers.test.lua
new file mode 100644
index 000000000..5f61a59f9
--- /dev/null
+++ b/test/replication/gh-5819-election-triggers.test.lua
@@ -0,0 +1,53 @@
+test_run = require('test_run').new()
+
+box.schema.user.grant('guest', 'replication')
+test_run:cmd('create server replica with rpl_master=default,\
+	      script="replication/replica.lua"')
+test_run:cmd('start server replica')
+
+repl = test_run:eval('replica', 'return box.cfg.listen')[1]
+box.cfg{replication = repl}
+test_run:switch('replica')
+box.cfg{election_mode='voter'}
+test_run:switch('default')
+
+election_tbl = {}
+
+function trig()\
+    election_tbl[#election_tbl+1] = box.info.election\
+end
+
+_ = box.ctl.on_election(trig)
+
+box.cfg{replication_synchro_quorum=2}
+box.cfg{election_mode='candidate'}
+
+test_run:wait_cond(function() return box.info.election.state == 'leader' end)
+assert(#election_tbl == 3)
+assert(election_tbl[1].state == 'follower')
+assert(election_tbl[2].state == 'candidate')
+assert(election_tbl[2].vote == 1)
+assert(election_tbl[3].state == 'leader')
+box.cfg{election_mode='voter'}
+
+assert(#election_tbl == 4)
+assert(election_tbl[4].state == 'follower')
+
+box.cfg{election_mode='off'}
+assert(#election_tbl == 5)
+
+box.cfg{election_mode='manual'}
+
+assert(#election_tbl == 6)
+assert(election_tbl[6].state == 'follower')
+
+box.ctl.promote()
+
+assert(#election_tbl == 9)
+assert(election_tbl[7].state == 'follower')
+assert(election_tbl[8].state == 'candidate')
+assert(election_tbl[9].state == 'leader')
+
+test_run:cmd('stop server replica')
+test_run:cmd('delete server replica')
+box.schema.user.revoke('guest', 'replication')
diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
index a51a2d51a..f2af00038 100644
--- a/test/replication/suite.cfg
+++ b/test/replication/suite.cfg
@@ -46,6 +46,7 @@
     "gh-5536-wal-limit.test.lua": {},
     "gh-5566-final-join-synchro.test.lua": {},
     "gh-5613-bootstrap-prefer-booted.test.lua": {},
+    "gh-5819-election-triggers.test.lua": {},
     "gh-6027-applier-error-show.test.lua": {},
     "gh-6032-promote-wal-write.test.lua": {},
     "gh-6057-qsync-confirm-async-no-wal.test.lua": {},
-- 
2.30.1 (Apple Git-130)


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Tarantool-patches] [PATCH] box: introduce on_election triggers
  2021-07-22  7:20 [Tarantool-patches] [PATCH] box: introduce on_election triggers Serge Petrenko via Tarantool-patches
@ 2021-07-26 20:27 ` Vladislav Shpilevoy via Tarantool-patches
  2021-07-28 10:03   ` Sergey Petrenko via Tarantool-patches
  0 siblings, 1 reply; 5+ messages in thread
From: Vladislav Shpilevoy via Tarantool-patches @ 2021-07-26 20:27 UTC (permalink / raw)
  To: Serge Petrenko, gorcunov; +Cc: tarantool-patches

Hi! Thanks for the patch!

See 3 comments below.

> diff --git a/src/box/raft.c b/src/box/raft.c
> index 7f787c0c5..c9c3ba818 100644
> --- a/src/box/raft.c
> +++ b/src/box/raft.c
> @@ -52,6 +52,8 @@ enum election_mode box_election_mode = ELECTION_MODE_INVALID;
>   */
>  static struct trigger box_raft_on_update;
>  
> +struct rlist box_raft_on_state = RLIST_HEAD_INITIALIZER(box_raft_on_state);

1. I propose to call it 'box_raft_on_update'. We usually use 'on_<action>'
naming pattern.

> +
>  /**
>   * Worker fiber does all the asynchronous work, which may need yields and can be
>   * long. These are WAL writes, network broadcasts. That allows not to block the
> @@ -274,6 +276,7 @@ box_raft_broadcast(struct raft *raft, const struct raft_msg *msg)
>  	assert(raft == box_raft());
>  	struct raft_request req;
>  	box_raft_msg_to_request(msg, &req);
> +	trigger_run(&box_raft_on_state, NULL);

2. Maybe call it after the state is pushed to the relays? So as it
would be sent earlier in case the triggers are going to yield.

>  	replicaset_foreach(replica)
>  		relay_push_raft(replica->relay, &req);
>  }
> diff --git a/test/replication/gh-5819-election-triggers.result b/test/replication/gh-5819-election-triggers.result
> new file mode 100644
> index 000000000..546aac8a2
> --- /dev/null
> +++ b/test/replication/gh-5819-election-triggers.result

3. Hm, I think we are supposed to use gh-#### file naming only for
bugfixes.
https://github.com/tarantool/tarantool/wiki/Code-review-procedure#testing

This is a feature, hence can have a normal name, or be in an existing
test file which is also not bound to a single ticket.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Tarantool-patches] [PATCH] box: introduce on_election triggers
  2021-07-26 20:27 ` Vladislav Shpilevoy via Tarantool-patches
@ 2021-07-28 10:03   ` Sergey Petrenko via Tarantool-patches
  2021-07-29 21:45     ` Vladislav Shpilevoy via Tarantool-patches
  0 siblings, 1 reply; 5+ messages in thread
From: Sergey Petrenko via Tarantool-patches @ 2021-07-28 10:03 UTC (permalink / raw)
  To: Vladislav Shpilevoy, gorcunov; +Cc: tarantool-patches


26.07.2021 23:27, Vladislav Shpilevoy пишет:
> Hi! Thanks for the patch!
>
> See 3 comments below.


Thanks for the review!


>> diff --git a/src/box/raft.c b/src/box/raft.c
>> index 7f787c0c5..c9c3ba818 100644
>> --- a/src/box/raft.c
>> +++ b/src/box/raft.c
>> @@ -52,6 +52,8 @@ enum election_mode box_election_mode = ELECTION_MODE_INVALID;
>>    */
>>   static struct trigger box_raft_on_update;
>>   
>> +struct rlist box_raft_on_state = RLIST_HEAD_INITIALIZER(box_raft_on_state);
> 1. I propose to call it 'box_raft_on_update'. We usually use 'on_<action>'
> naming pattern.


box_raft_on_update is already occupied by internal triggers which can't 
yield.
I propose box_raft_on_broadcast then. Besides, the triggers are really 
run on a
broadcast.


>
>> +
>>   /**
>>    * Worker fiber does all the asynchronous work, which may need yields and can be
>>    * long. These are WAL writes, network broadcasts. That allows not to block the
>> @@ -274,6 +276,7 @@ box_raft_broadcast(struct raft *raft, const struct raft_msg *msg)
>>   	assert(raft == box_raft());
>>   	struct raft_request req;
>>   	box_raft_msg_to_request(msg, &req);
>> +	trigger_run(&box_raft_on_state, NULL);
> 2. Maybe call it after the state is pushed to the relays? So as it
> would be sent earlier in case the triggers are going to yield.


Ok, no problem.


>
>>   	replicaset_foreach(replica)
>>   		relay_push_raft(replica->relay, &req);
>>   }
>> diff --git a/test/replication/gh-5819-election-triggers.result b/test/replication/gh-5819-election-triggers.result
>> new file mode 100644
>> index 000000000..546aac8a2
>> --- /dev/null
>> +++ b/test/replication/gh-5819-election-triggers.result
> 3. Hm, I think we are supposed to use gh-#### file naming only for
> bugfixes.
> https://github.com/tarantool/tarantool/wiki/Code-review-procedure#testing
>
> This is a feature, hence can have a normal name, or be in an existing
> test file which is also not bound to a single ticket.

Yeah, sorry.

Here's the diff:

=============================

diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 4b2a467d8..4a9212f33 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -85,7 +85,7 @@ lbox_ctl_on_schema_init(struct lua_State *L)
  static int
  lbox_ctl_on_election(struct lua_State *L)
  {
-       return lbox_trigger_reset(L, 2, &box_raft_on_state, NULL, NULL);
+       return lbox_trigger_reset(L, 2, &box_raft_on_broadcast, NULL, NULL);
  }

  static int
diff --git a/src/box/raft.c b/src/box/raft.c
index c9c3ba818..38cfc0cf3 100644
--- a/src/box/raft.c
+++ b/src/box/raft.c
@@ -52,7 +52,8 @@ enum election_mode box_election_mode = 
ELECTION_MODE_INVALID;
   */
  static struct trigger box_raft_on_update;

-struct rlist box_raft_on_state = RLIST_HEAD_INITIALIZER(box_raft_on_state);
+struct rlist box_raft_on_broadcast =
+       RLIST_HEAD_INITIALIZER(box_raft_on_broadcast);

  /**
   * Worker fiber does all the asynchronous work, which may need yields 
and can be
@@ -276,9 +277,9 @@ box_raft_broadcast(struct raft *raft, const struct 
raft_msg *msg)
         assert(raft == box_raft());
         struct raft_request req;
         box_raft_msg_to_request(msg, &req);
-       trigger_run(&box_raft_on_state, NULL);
         replicaset_foreach(replica)
                 relay_push_raft(replica->relay, &req);
+       trigger_run(&box_raft_on_broadcast, NULL);
  }

  static void
diff --git a/src/box/raft.h b/src/box/raft.h
index dbe16eebf..125bc64e0 100644
--- a/src/box/raft.h
+++ b/src/box/raft.h
@@ -37,10 +37,10 @@ extern "C" {
  #endif

  /**
- * A public trigger fired on Raft state change. It's allowed to yield 
inside
- * it, and it's run asynchronously.
~/Documents/Source/tarantool/test ❯ git diff > 1.dff
~/Documents/Source/tarantool/test ❯ cat 1.dff
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index 4b2a467d8..4a9212f33 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -85,7 +85,7 @@ lbox_ctl_on_schema_init(struct lua_State *L)
  static int
  lbox_ctl_on_election(struct lua_State *L)
  {
-    return lbox_trigger_reset(L, 2, &box_raft_on_state, NULL, NULL);
+    return lbox_trigger_reset(L, 2, &box_raft_on_broadcast, NULL, NULL);
  }

  static int
diff --git a/src/box/raft.c b/src/box/raft.c
index c9c3ba818..38cfc0cf3 100644
--- a/src/box/raft.c
+++ b/src/box/raft.c
@@ -52,7 +52,8 @@ enum election_mode box_election_mode = 
ELECTION_MODE_INVALID;
   */
  static struct trigger box_raft_on_update;

-struct rlist box_raft_on_state = RLIST_HEAD_INITIALIZER(box_raft_on_state);
+struct rlist box_raft_on_broadcast =
+    RLIST_HEAD_INITIALIZER(box_raft_on_broadcast);

  /**
   * Worker fiber does all the asynchronous work, which may need yields 
and can be
@@ -276,9 +277,9 @@ box_raft_broadcast(struct raft *raft, const struct 
raft_msg *msg)
      assert(raft == box_raft());
      struct raft_request req;
      box_raft_msg_to_request(msg, &req);
-    trigger_run(&box_raft_on_state, NULL);
      replicaset_foreach(replica)
          relay_push_raft(replica->relay, &req);
+    trigger_run(&box_raft_on_broadcast, NULL);
  }

  static void
diff --git a/src/box/raft.h b/src/box/raft.h
index dbe16eebf..125bc64e0 100644
--- a/src/box/raft.h
+++ b/src/box/raft.h
@@ -37,10 +37,10 @@ extern "C" {
  #endif

  /**
- * A public trigger fired on Raft state change. It's allowed to yield 
inside
- * it, and it's run asynchronously.
+ * A public trigger fired on Raft state change, i.e. on a broadcast.
+ * It's allowed to yield inside it, and it's run asynchronously.
   */
-extern struct rlist box_raft_on_state;
+extern struct rlist box_raft_on_broadcast;

  enum election_mode {
      ELECTION_MODE_INVALID = -1,
diff --git a/test/replication/election_basic.result 
b/test/replication/election_basic.result
index b64028c60..fc7121d7f 100644
--- a/test/replication/election_basic.result
+++ b/test/replication/election_basic.result
@@ -275,3 +275,147 @@ test_run:cmd(string.format('start server %s', 
leader_name))
  test_run:drop_cluster(SERVERS)
   | ---
   | ...
+
+-- gh-5819: on_election triggers, that are filed on every visible state 
change.
+box.schema.user.grant('guest', 'replication')
+ | ---
+ | ...
+test_run:cmd('create server replica with rpl_master=default,\
+          script="replication/replica.lua"')
+ | ---
+ | - true
+ | ...
+test_run:cmd('start server replica')
+ | ---
+ | - true
+ | ...
+
+repl = test_run:eval('replica', 'return box.cfg.listen')[1]
+ | ---
+ | ...
+box.cfg{replication = repl}
+ | ---
+ | ...
+test_run:switch('replica')
+ | ---
+ | - true
+ | ...
+box.cfg{election_mode='voter'}
+ | ---
+ | ...
+test_run:switch('default')
+ | ---
+ | - true
+ | ...
+
+election_tbl = {}
+ | ---
+ | ...
+
+function trig()\
+    election_tbl[#election_tbl+1] = box.info.election\
+end
+ | ---
+ | ...
+
+_ = box.ctl.on_election(trig)
+ | ---
+ | ...
+
+box.cfg{replication_synchro_quorum=2}
+ | ---
+ | ...
+box.cfg{election_mode='candidate'}
+ | ---
+ | ...
+
+test_run:wait_cond(function() return #election_tbl == 3 end)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[1].state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[2].state == 'candidate')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[2].vote == 1)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[3].state == 'leader')
+ | ---
+ | - true
+ | ...
+
+box.cfg{election_mode='voter'}
+ | ---
+ | ...
+test_run:wait_cond(function() return #election_tbl == 4 end)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[4].state == 'follower')
+ | ---
+ | - true
+ | ...
+
+box.cfg{election_mode='off'}
+ | ---
+ | ...
+test_run:wait_cond(function() return #election_tbl == 5 end)
+ | ---
+ | - true
+ | ...
+
+box.cfg{election_mode='manual'}
+ | ---
+ | ...
+test_run:wait_cond(function() return #election_tbl == 6 end)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[6].state == 'follower')
+ | ---
+ | - true
+ | ...
+
+box.ctl.promote()
+ | ---
+ | ...
+
+test_run:wait_cond(function() return #election_tbl == 9 end)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[7].state == 'follower')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[7].term == election_tbl[6].term + 1)
+ | ---
+ | - true
+ | ...
+assert(election_tbl[8].state == 'candidate')
+ | ---
+ | - true
+ | ...
+assert(election_tbl[9].state == 'leader')
+ | ---
+ | - true
+ | ...
+
+test_run:cmd('stop server replica')
+ | ---
+ | - true
+ | ...
+test_run:cmd('delete server replica')
+ | ---
+ | - true
+ | ...
+
+box.schema.user.revoke('guest', 'replication')
+ | ---
+ | ...
diff --git a/test/replication/election_basic.test.lua 
b/test/replication/election_basic.test.lua
index 77fdf6340..f1330d232 100644
--- a/test/replication/election_basic.test.lua
+++ b/test/replication/election_basic.test.lua
@@ -116,3 +116,56 @@ assert(r1_leader == r2_leader)
  test_run:cmd(string.format('start server %s', leader_name))

  test_run:drop_cluster(SERVERS)
+
+-- gh-5819: on_election triggers, that are filed on every visible state 
change.
+box.schema.user.grant('guest', 'replication')
+test_run:cmd('create server replica with rpl_master=default,\
+          script="replication/replica.lua"')
+test_run:cmd('start server replica')
+
+repl = test_run:eval('replica', 'return box.cfg.listen')[1]
+box.cfg{replication = repl}
+test_run:switch('replica')
+box.cfg{election_mode='voter'}
+test_run:switch('default')
+
+election_tbl = {}
+
+function trig()\
+    election_tbl[#election_tbl+1] = box.info.election\
+end
+
+_ = box.ctl.on_election(trig)
+
+box.cfg{replication_synchro_quorum=2}
+box.cfg{election_mode='candidate'}
+
+test_run:wait_cond(function() return #election_tbl == 3 end)
+assert(election_tbl[1].state == 'follower')
+assert(election_tbl[2].state == 'candidate')
+assert(election_tbl[2].vote == 1)
+assert(election_tbl[3].state == 'leader')
+
+box.cfg{election_mode='voter'}
+test_run:wait_cond(function() return #election_tbl == 4 end)
+assert(election_tbl[4].state == 'follower')
+
+box.cfg{election_mode='off'}
+test_run:wait_cond(function() return #election_tbl == 5 end)
+
+box.cfg{election_mode='manual'}
+test_run:wait_cond(function() return #election_tbl == 6 end)
+assert(election_tbl[6].state == 'follower')
+
+box.ctl.promote()
+
+test_run:wait_cond(function() return #election_tbl == 9 end)
+assert(election_tbl[7].state == 'follower')
+assert(election_tbl[7].term == election_tbl[6].term + 1)
+assert(election_tbl[8].state == 'candidate')
+assert(election_tbl[9].state == 'leader')
+
+test_run:cmd('stop server replica')
+test_run:cmd('delete server replica')
+
+box.schema.user.revoke('guest', 'replication')
diff --git a/test/replication/gh-5819-election-triggers.result 
b/test/replication/gh-5819-election-triggers.result
deleted file mode 100644
index 546aac8a2..000000000
--- a/test/replication/gh-5819-election-triggers.result
+++ /dev/null
@@ -1,147 +0,0 @@
--- test-run result file version 2
-test_run = require('test_run').new()
- | ---
- | ...
-
-box.schema.user.grant('guest', 'replication')
- | ---
- | ...
-test_run:cmd('create server replica with rpl_master=default,\
-          script="replication/replica.lua"')
- | ---
- | - true
- | ...
-test_run:cmd('start server replica')
- | ---
- | - true
- | ...
-
-repl = test_run:eval('replica', 'return box.cfg.listen')[1]
- | ---
- | ...
-box.cfg{replication = repl}
- | ---
- | ...
-test_run:switch('replica')
- | ---
- | - true
- | ...
-box.cfg{election_mode='voter'}
- | ---
- | ...
-test_run:switch('default')
- | ---
- | - true
- | ...
-
-election_tbl = {}
- | ---
- | ...
-
-function trig()\
-    election_tbl[#election_tbl+1] = box.info.election\
-end
- | ---
- | ...
-
-_ = box.ctl.on_election(trig)
- | ---
- | ...
-
-box.cfg{replication_synchro_quorum=2}
- | ---
- | ...
-box.cfg{election_mode='candidate'}
- | ---
- | ...
-
-test_run:wait_cond(function() return box.info.election.state == 
'leader' end)
- | ---
- | - true
- | ...
-assert(#election_tbl == 3)
- | ---
- | - true
- | ...
-assert(election_tbl[1].state == 'follower')
- | ---
- | - true
- | ...
-assert(election_tbl[2].state == 'candidate')
- | ---
- | - true
- | ...
-assert(election_tbl[2].vote == 1)
- | ---
- | - true
- | ...
-assert(election_tbl[3].state == 'leader')
- | ---
- | - true
- | ...
-box.cfg{election_mode='voter'}
- | ---
- | ...
-
-assert(#election_tbl == 4)
- | ---
- | - true
- | ...
-assert(election_tbl[4].state == 'follower')
- | ---
- | - true
- | ...
-
-box.cfg{election_mode='off'}
- | ---
- | ...
-assert(#election_tbl == 5)
- | ---
- | - true
- | ...
-
-box.cfg{election_mode='manual'}
- | ---
- | ...
-
-assert(#election_tbl == 6)
- | ---
- | - true
- | ...
-assert(election_tbl[6].state == 'follower')
- | ---
- | - true
- | ...
-
-box.ctl.promote()
- | ---
- | ...
-
-assert(#election_tbl == 9)
- | ---
- | - true
- | ...
-assert(election_tbl[7].state == 'follower')
- | ---
- | - true
- | ...
-assert(election_tbl[8].state == 'candidate')
- | ---
- | - true
- | ...
-assert(election_tbl[9].state == 'leader')
- | ---
- | - true
- | ...
-
-test_run:cmd('stop server replica')
- | ---
- | - true
- | ...
-test_run:cmd('delete server replica')
- | ---
- | - true
- | ...
-box.schema.user.revoke('guest', 'replication')
- | ---
- | ...
diff --git a/test/replication/gh-5819-election-triggers.test.lua 
b/test/replication/gh-5819-election-triggers.test.lua
deleted file mode 100644
index 5f61a59f9..000000000
--- a/test/replication/gh-5819-election-triggers.test.lua
+++ /dev/null
@@ -1,53 +0,0 @@
-test_run = require('test_run').new()
-
-box.schema.user.grant('guest', 'replication')
-test_run:cmd('create server replica with rpl_master=default,\
-          script="replication/replica.lua"')
-test_run:cmd('start server replica')
-
-repl = test_run:eval('replica', 'return box.cfg.listen')[1]
-box.cfg{replication = repl}
-test_run:switch('replica')
-box.cfg{election_mode='voter'}
-test_run:switch('default')
-
-election_tbl = {}
-
-function trig()\
-    election_tbl[#election_tbl+1] = box.info.election\
-end
-
-_ = box.ctl.on_election(trig)
-
-box.cfg{replication_synchro_quorum=2}
-box.cfg{election_mode='candidate'}
-
-test_run:wait_cond(function() return box.info.election.state == 
'leader' end)
-assert(#election_tbl == 3)
-assert(election_tbl[1].state == 'follower')
-assert(election_tbl[2].state == 'candidate')
-assert(election_tbl[2].vote == 1)
-assert(election_tbl[3].state == 'leader')
-box.cfg{election_mode='voter'}
-
-assert(#election_tbl == 4)
-assert(election_tbl[4].state == 'follower')
-
-box.cfg{election_mode='off'}
-assert(#election_tbl == 5)
-
-box.cfg{election_mode='manual'}
-
-assert(#election_tbl == 6)
-assert(election_tbl[6].state == 'follower')
-
-box.ctl.promote()
-
-assert(#election_tbl == 9)
-assert(election_tbl[7].state == 'follower')
-assert(election_tbl[8].state == 'candidate')
-assert(election_tbl[9].state == 'leader')
-
-test_run:cmd('stop server replica')
-test_run:cmd('delete server replica')
-box.schema.user.revoke('guest', 'replication')
diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
index f2af00038..a51a2d51a 100644
--- a/test/replication/suite.cfg
+++ b/test/replication/suite.cfg
@@ -46,7 +46,6 @@
      "gh-5536-wal-limit.test.lua": {},
      "gh-5566-final-join-synchro.test.lua": {},
      "gh-5613-bootstrap-prefer-booted.test.lua": {},
-    "gh-5819-election-triggers.test.lua": {},
      "gh-6027-applier-error-show.test.lua": {},
      "gh-6032-promote-wal-write.test.lua": {},
      "gh-6057-qsync-confirm-async-no-wal.test.lua": {},

=============================


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Tarantool-patches] [PATCH] box: introduce on_election triggers
  2021-07-28 10:03   ` Sergey Petrenko via Tarantool-patches
@ 2021-07-29 21:45     ` Vladislav Shpilevoy via Tarantool-patches
  2021-08-06  9:49       ` Vitaliia Ioffe via Tarantool-patches
  0 siblings, 1 reply; 5+ messages in thread
From: Vladislav Shpilevoy via Tarantool-patches @ 2021-07-29 21:45 UTC (permalink / raw)
  To: Sergey Petrenko, gorcunov; +Cc: tarantool-patches

Hi! Thanks for the fixes!

LGTM.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Tarantool-patches]  [PATCH] box: introduce on_election triggers
  2021-07-29 21:45     ` Vladislav Shpilevoy via Tarantool-patches
@ 2021-08-06  9:49       ` Vitaliia Ioffe via Tarantool-patches
  0 siblings, 0 replies; 5+ messages in thread
From: Vitaliia Ioffe via Tarantool-patches @ 2021-08-06  9:49 UTC (permalink / raw)
  To: Vladislav Shpilevoy; +Cc: tarantool-patches

[-- Attachment #1: Type: text/plain, Size: 229 bytes --]


Hi team, 
 
QA LGTM
 
 
--
Vitaliia Ioffe
 
  
>Пятница, 30 июля 2021, 0:45 +03:00 от Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org>:
> 
>Hi! Thanks for the fixes!
>
>LGTM.
 

[-- Attachment #2: Type: text/html, Size: 694 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-08-06  9:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-22  7:20 [Tarantool-patches] [PATCH] box: introduce on_election triggers Serge Petrenko via Tarantool-patches
2021-07-26 20:27 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-28 10:03   ` Sergey Petrenko via Tarantool-patches
2021-07-29 21:45     ` Vladislav Shpilevoy via Tarantool-patches
2021-08-06  9:49       ` Vitaliia Ioffe via Tarantool-patches

Tarantool development patches archive

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://lists.tarantool.org/tarantool-patches/0 tarantool-patches/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 tarantool-patches tarantool-patches/ https://lists.tarantool.org/tarantool-patches \
		tarantool-patches@dev.tarantool.org.
	public-inbox-index tarantool-patches

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git