diff --git a/src/node_state/common/mod.rs b/src/node_state/common/mod.rs index da21bbd..505c1ab 100644 --- a/src/node_state/common/mod.rs +++ b/src/node_state/common/mod.rs @@ -190,7 +190,11 @@ where } /// `Follower`状態に遷移する. - pub fn transit_to_follower(&mut self, followee: NodeId) -> RoleState { + pub fn transit_to_follower( + &mut self, + followee: NodeId, + pending_vote: Option, + ) -> RoleState { self.metrics.transit_to_follower_total.increment(); let new_ballot = Ballot { term: self.local_node.ballot.term, @@ -198,7 +202,7 @@ where }; self.set_ballot(new_ballot); self.set_role(Role::Follower); - RoleState::Follower(Follower::new(self)) + RoleState::Follower(Follower::new(self, pending_vote)) } /// 次のメッセージ送信に使用されるシーケンス番号を返す. @@ -309,8 +313,7 @@ where if m.log_tail.is_newer_or_equal_than(self.history.tail()) { // 送信者(候補者)のログは十分に新しいので、その人を支持する let candidate = m.header.sender.clone(); - self.unread_message = Some(Message::RequestVoteCall(m)); - self.transit_to_follower(candidate) + self.transit_to_follower(candidate, Some(m.header)) } else { // ローカルログの方が新しいので、自分で立候補する self.transit_to_candidate() @@ -319,12 +322,12 @@ where // 新リーダが当選していたので、その人のフォロワーとなる let leader = message.header().sender.clone(); self.unread_message = Some(message); - self.transit_to_follower(leader) + self.transit_to_follower(leader, None) } else if self.local_node.role == Role::Leader { self.transit_to_candidate() } else { let local = self.local_node.id.clone(); - self.transit_to_follower(local) + self.transit_to_follower(local, None) }; HandleMessageResult::Handled(Some(next_state)) } else if message.header().term < self.local_node.ballot.term { @@ -345,7 +348,7 @@ where // リーダが確定したので、フォロー先を変更する let leader = message.header().sender.clone(); self.unread_message = Some(message); - let next = self.transit_to_follower(leader); + let next = self.transit_to_follower(leader, None); HandleMessageResult::Handled(Some(next)) } _ => HandleMessageResult::Unhandled(message), // 個別のロールに処理を任せる diff --git a/src/node_state/follower/init.rs b/src/node_state/follower/init.rs index 4257d05..6cb0278 100644 --- a/src/node_state/follower/init.rs +++ b/src/node_state/follower/init.rs @@ -16,11 +16,11 @@ pub struct FollowerInit { pending_vote: Option, } impl FollowerInit { - pub fn new(common: &mut Common) -> Self { + pub fn new(common: &mut Common, pending_vote: Option) -> Self { let future = common.save_ballot(); FollowerInit { future, - pending_vote: None, + pending_vote, } } pub fn handle_message( @@ -30,6 +30,7 @@ impl FollowerInit { ) -> Result> { match message { Message::RequestVoteCall(m) => { + // pending_vote can be overwritten here because the latest vote should be used. self.pending_vote = Some(m.header); } Message::AppendEntriesCall(m) => { diff --git a/src/node_state/follower/mod.rs b/src/node_state/follower/mod.rs index 8fb5949..0539497 100644 --- a/src/node_state/follower/mod.rs +++ b/src/node_state/follower/mod.rs @@ -4,7 +4,7 @@ use self::init::FollowerInit; use self::snapshot::FollowerSnapshot; use super::{Common, NextState}; use election::Role; -use message::Message; +use message::{Message, MessageHeader}; use {Io, Result}; mod append; @@ -32,9 +32,9 @@ pub enum Follower { Snapshot(FollowerSnapshot), } impl Follower { - pub fn new(common: &mut Common) -> Self { + pub fn new(common: &mut Common, pending_vote: Option) -> Self { common.set_timeout(Role::Follower); - let follower = FollowerInit::new(common); + let follower = FollowerInit::new(common, pending_vote); Follower::Init(follower) } pub fn handle_timeout(&mut self, common: &mut Common) -> Result> {