diff --git a/src/luamod.rs b/src/luamod.rs index f3979782b8e63f44c5d0155fdd327b55863bd6d4..86cdd25c98a85da4f119e6b95dbd820d11ad5d5a 100644 --- a/src/luamod.rs +++ b/src/luamod.rs @@ -647,11 +647,11 @@ pub(crate) fn setup(args: &args::Run) { let node = traft::node::global()?; let mut node_impl = node.node_impl(); - let index = node_impl.propose(op)?; + let entry_id = node_impl.propose_async(op)?; node.main_loop.wakeup(); // Release the lock drop(node_impl); - Ok(index) + Ok(entry_id.index) }), ); diff --git a/src/traft/node.rs b/src/traft/node.rs index 0fb14f4fce5cb3dd92133420e0fa731a37bfaa01..0c77cb046d8a751d16021b6359b5acde09ee2378 100644 --- a/src/traft/node.rs +++ b/src/traft/node.rs @@ -517,14 +517,24 @@ impl NodeImpl { /// /// Returns id of the proposed entry, which can be used to await it's /// application. - /// NOTE: the entry may not actually be committed, and the entry at that + /// + /// Returns an error if current instance is not a raft leader, because + /// followers should propose raft log entries via [`proc_cas`]. + /// + /// NOTE: the proposed entry may still be dropped, and the entry at that /// index may be some other one. It's the callers responsibility to verify /// which entry got committed. + /// + /// [`proc_cas`]: crate::cas::proc_cas #[inline] - pub fn propose_async<T>(&mut self, op: T) -> Result<RaftEntryId, RaftError> + pub fn propose_async<T>(&mut self, op: T) -> Result<RaftEntryId, Error> where T: Into<Op>, { + if self.raw_node.raft.state != RaftStateRole::Leader { + return Err(Error::NotALeader); + } + let index_before = self.raw_node.raft.raft_log.last_index(); let ctx = traft::EntryContext::Op(op.into()); @@ -538,17 +548,6 @@ impl NodeImpl { Ok(entry_id) } - /// Proposes a raft entry to be appended to the log and returns raft index - /// at which it is expected to be committed unless it gets rejected. - /// - /// **Doesn't yield** - pub fn propose(&mut self, op: Op) -> Result<RaftIndex, RaftError> { - let ctx = traft::EntryContext::Op(op); - self.raw_node.propose(ctx.into_raft_ctx(), vec![])?; - let index = self.raw_node.raft.raft_log.last_index(); - Ok(index) - } - pub fn campaign(&mut self) -> Result<(), RaftError> { self.raw_node.campaign() } diff --git a/test/int/test_couple.py b/test/int/test_couple.py index 0674e7a3857c48ec6a7b02d1adcecf58866f3067..ce5541b932417603622a1e40f88c4b6117d29ed3 100644 --- a/test/int/test_couple.py +++ b/test/int/test_couple.py @@ -8,15 +8,6 @@ def cluster2(cluster: Cluster): return cluster -def test_follower_proposal(cluster2: Cluster): - i1, i2 = cluster2.instances - i1.promote_or_fail() - - i2.assert_raft_status("Follower", leader_id=i1.raft_id) - - i2.raft_propose_nop() - - def test_switchover(cluster2: Cluster): i1, i2 = cluster2.instances @@ -76,7 +67,6 @@ def test_restart_leader(cluster2: Cluster): i1.restart() i1.wait_online() assert i1.current_grade() == dict(variant="Online", incarnation=2) - i1.raft_propose_nop() i1.restart() i1.wait_online()