-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature:
Raft::trigger()::allow_next_revert()
allow to reset replic…
…ation for next detected follower log revert This method requests the RaftCore to allow to reset replication for a specific node when log revert is detected. - `allow=true`: This method instructs the RaftCore to allow the target node's log to revert to a previous state for one time. - `allow=false`: This method instructs the RaftCore to panic if the target node's log revert This method returns `Fatal` error if failed to send the request to RaftCore, e.g. when RaftCore is shut down. Otherwise, it returns a `Ok(Result<_,_>)`, the inner result is: - `Ok(())` if the request is successfully processed, - or `Err(AllowNextRevertError)` explaining why the request is rejected. ### Behavior - If this node is the Leader, it will attempt to replicate logs to the target node from the beginning. - If this node is not the Leader, the request is ignored. - If the target node is not found, the request is ignored. ### Automatic Replication Reset When the `loosen-follower-log-revert` feature flag is enabled, the Leader automatically reset replication if it detects that the target node's log has reverted. This feature is primarily useful in testing environments. ### Production Considerations In production environments, state reversion is a critical issue that should not be automatically handled. However, there may be scenarios where a Follower's data is intentionally removed and needs to rejoin the cluster(without membership changes). In such cases, the Leader should reinitialize replication for that node with the following steps: - Shut down the target node. - call [`Self::allow_next_revert`] on the Leader. - Clear the target node's data directory. - Restart the target node. - Fix: #1251
- Loading branch information
1 parent
3ab0d49
commit 47e0220
Showing
14 changed files
with
349 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::error::ForwardToLeader; | ||
use crate::error::NodeNotFound; | ||
use crate::RaftTypeConfig; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] | ||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))] | ||
pub enum AllowNextRevertError<C: RaftTypeConfig> { | ||
#[error("Can not set allow_next_revert; error: {0}")] | ||
NodeNotFound(#[from] NodeNotFound<C>), | ||
#[error("Can not set allow_next_revert; error: {0}")] | ||
ForwardToLeader(#[from] ForwardToLeader<C>), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use crate::error::Operation; | ||
use crate::RaftTypeConfig; | ||
|
||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] | ||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))] | ||
#[error("Node {node_id} not found when: ({operation})")] | ||
pub struct NodeNotFound<C: RaftTypeConfig> { | ||
pub node_id: C::NodeId, | ||
pub operation: Operation, | ||
} | ||
|
||
impl<C: RaftTypeConfig> NodeNotFound<C> { | ||
pub fn new(node_id: C::NodeId, operation: Operation) -> Self { | ||
Self { node_id, operation } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
use std::fmt; | ||
|
||
/// Operations that can be executed on a Raft node. | ||
/// | ||
/// These commands represent operations that affect the Raft node's behavior or state. They are | ||
/// primarily used in error reporting to provide context about what operation was attempted when an | ||
/// error occurred. | ||
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] | ||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))] | ||
pub enum Operation { | ||
/// Set a flag to allow a target replication state to revert to a previous state for one time. | ||
AllowNextRevert, | ||
|
||
/// Transfer leadership to the specified node. | ||
TransferLeader, | ||
|
||
/// Send a heartbeat message to a follower or learner. | ||
SendHeartbeat, | ||
|
||
/// Receive a snapshot. | ||
ReceiveSnapshot, | ||
|
||
/// Install a snapshot. | ||
InstallSnapshot, | ||
|
||
/// Write application data via Raft protocol. | ||
ClientWrite, | ||
|
||
/// Initialize an empty Raft node with a cluster membership config. | ||
Initialize, | ||
|
||
/// Start an election. | ||
Elect, | ||
} | ||
|
||
impl fmt::Display for Operation { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match self { | ||
Operation::AllowNextRevert => write!(f, "set flag to allow replication revert for once"), | ||
Operation::TransferLeader => write!(f, "transfer leadership"), | ||
Operation::SendHeartbeat => write!(f, "send heartbeat"), | ||
Operation::ReceiveSnapshot => write!(f, "receive snapshot"), | ||
Operation::InstallSnapshot => write!(f, "install snapshot"), | ||
Operation::ClientWrite => write!(f, "write application data"), | ||
Operation::Initialize => write!(f, "initialize"), | ||
Operation::Elect => write!(f, "elect"), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.