From c8813d84d54d503e7dcb7af0fc9926e6b4720ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=82=8E=E6=B3=BC?= Date: Sat, 30 Nov 2024 12:17:40 +0800 Subject: [PATCH] Change: Replace `loosen-follower-log-revert` feature flag with `Config::allow_log_reversion` The `loosen-follower-log-revert` feature flag is removed in favor of a runtime-configurable option, `Config::allow_log_reversion`. This change allows log reversion to be controlled dynamically via application configuration rather than at compile time. When `Config::allow_log_reversion` is enabled, log reversion on a Follower is always permitted. Upon detecting a reversion, the Leader will reset replication from the beginning instead of panicking. ### Breaking Change: Since this commit, compiling with `--features loosen-follower-log-revert` will now result in the following error: ```text error: The feature flag `loosen-follower-log-revert` is removed since version `0.10.0`. Use `Config::allow_log_reversion` instead. ``` Upgrade tip: For applications relying on `loosen-follower-log-revert`: 1. **Remove this feature flag** from `Cargo.toml`. 2. **Enable log reversion in your configuration** as follows: ```rust let config = Config { allow_log_reversion: Some(true), ..Default::default() }; ``` --- .github/workflows/ci.yaml | 3 - openraft/Cargo.toml | 3 +- openraft/src/config/config.rs | 28 ++++++ openraft/src/config/config_test.rs | 28 ++++++ openraft/src/docs/faq/faq.md | 7 +- .../docs/feature_flags/feature-flags-toc.md | 1 - .../src/docs/feature_flags/feature-flags.md | 9 -- openraft/src/engine/engine_config.rs | 5 + .../engine/handler/replication_handler/mod.rs | 11 ++- openraft/src/engine/tests/startup_test.rs | 4 +- openraft/src/lib.rs | 6 ++ openraft/src/progress/entry/mod.rs | 84 +++-------------- openraft/src/progress/entry/tests.rs | 14 ++- openraft/src/progress/entry/update.rs | 94 +++++++++++++++++++ openraft/src/raft/trigger.rs | 7 +- openraft/src/vote/ref_vote.rs | 2 + tests/Cargo.toml | 1 - tests/tests/replication/main.rs | 1 - .../t60_feature_loosen_follower_log_revert.rs | 3 +- 19 files changed, 206 insertions(+), 105 deletions(-) create mode 100644 openraft/src/progress/entry/update.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index af4cfab10..fc0b0df44 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -313,9 +313,6 @@ jobs: - toolchain: "nightly" features: "single-term-leader" - - toolchain: "nightly" - features: "loosen-follower-log-revert" - steps: - name: Setup | Checkout diff --git a/openraft/Cargo.toml b/openraft/Cargo.toml index cdc5fe670..13bef2751 100644 --- a/openraft/Cargo.toml +++ b/openraft/Cargo.toml @@ -93,6 +93,8 @@ singlethreaded = ["openraft-macros/singlethreaded"] # useful for testing or other special scenarios. # For instance, in an even number nodes cluster, erasing a node's data and then # rebooting it(log reverts to empty) will not result in data loss. +# +# This feature is removed since `0.10.0`. Use `Config::allow_log_reversion` instead. loosen-follower-log-revert = [] @@ -110,7 +112,6 @@ tracing-log = [ "tracing/log" ] features = [ "bt", "compat", - "loosen-follower-log-revert", "serde", "tracing-log", ] diff --git a/openraft/src/config/config.rs b/openraft/src/config/config.rs index 174492308..110b79223 100644 --- a/openraft/src/config/config.rs +++ b/openraft/src/config/config.rs @@ -228,6 +228,26 @@ pub struct Config { default_missing_value = "true" )] pub enable_elect: bool, + + /// Whether to allow to reset the replication progress to `None`, when the + /// follower's log is found reverted to an early state. **Do not enable this in production** + /// unless you know what you are doing. + /// + /// Although log state reversion is typically seen as a bug, enabling it can be + /// useful for testing or other special scenarios. + /// For instance, in an even number nodes cluster, erasing a node's data and then + /// rebooting it(log reverts to empty) will not result in data loss. + /// + /// For one-shot log reversion, use + /// [`Raft::trigger().allow_next_revert()`](crate::raft::trigger::Trigger::allow_next_revert). + /// + /// Since: 0.10.0 + #[clap(long, + action = clap::ArgAction::Set, + num_args = 0..=1, + default_missing_value = "true" + )] + pub allow_log_reversion: Option, } /// Updatable config for a raft runtime. @@ -276,6 +296,14 @@ impl Config { } } + /// Whether to allow the replication to reset the state to `None` when a log state reversion is + /// detected. + /// + /// By default, it does not allow log reversion, because it might indicate a bug in the system. + pub(crate) fn get_allow_log_reversion(&self) -> bool { + self.allow_log_reversion.unwrap_or(false) + } + /// Build a `Config` instance from a series of command line arguments. /// /// The first element in `args` must be the application name. diff --git a/openraft/src/config/config_test.rs b/openraft/src/config/config_test.rs index 640ed6d80..21c4e6a54 100644 --- a/openraft/src/config/config_test.rs +++ b/openraft/src/config/config_test.rs @@ -162,3 +162,31 @@ fn test_config_enable_elect() -> anyhow::Result<()> { Ok(()) } + +#[test] +fn test_config_allow_log_reversion() -> anyhow::Result<()> { + let config = Config::build(&["foo", "--allow-log-reversion=false"])?; + assert_eq!(Some(false), config.allow_log_reversion); + + let config = Config::build(&["foo", "--allow-log-reversion=true"])?; + assert_eq!(Some(true), config.allow_log_reversion); + + let config = Config::build(&["foo", "--allow-log-reversion"])?; + assert_eq!(Some(true), config.allow_log_reversion); + + let mut config = Config::build(&["foo"])?; + assert_eq!(None, config.allow_log_reversion); + + // test allow_log_reversion method + + config.allow_log_reversion = None; + assert_eq!(false, config.get_allow_log_reversion()); + + config.allow_log_reversion = Some(true); + assert_eq!(true, config.get_allow_log_reversion()); + + config.allow_log_reversion = Some(false); + assert_eq!(false, config.get_allow_log_reversion()); + + Ok(()) +} diff --git a/openraft/src/docs/faq/faq.md b/openraft/src/docs/faq/faq.md index e0c426efc..48f6a28ff 100644 --- a/openraft/src/docs/faq/faq.md +++ b/openraft/src/docs/faq/faq.md @@ -184,7 +184,7 @@ behavior is **undefined**. ### Can I wipe out the data of ONE node and wait for the leader to replicate all data to it again? Avoid doing this. Doing so will panic the leader. But it is permitted -if [`loosen-follower-log-revert`] feature flag is enabled. +with config [`Config::allow_log_reversion`] enabled. In a raft cluster, although logs are replicated to multiple nodes, wiping out a node and restarting it is still possible to cause data loss. @@ -211,7 +211,7 @@ N5 | elect L2 But for even number nodes cluster, Erasing **exactly one** node won't cause data loss. Thus, in a special scenario like this, or for testing purpose, you can use -`--feature loosen-follower-log-revert` to permit erasing a node. +[`Config::allow_log_reversion`] to permit erasing a node. ### Is Openraft resilient to incorrectly configured clusters? @@ -237,7 +237,6 @@ pub(crate) fn following_handler(&mut self) -> FollowingHandler { ``` -[`loosen-follower-log-revert`]: `crate::docs::feature_flags#loosen_follower_log_revert` [`single-term-leader`]: `crate::docs::feature_flags#single_term_leader` [`Linearizable Read`]: `crate::docs::protocol::read` @@ -246,6 +245,8 @@ pub(crate) fn following_handler(&mut self) -> FollowingHandler { [`BasicNode`]: `crate::node::BasicNode` [`RaftTypeConfig`]: `crate::RaftTypeConfig` +[`Config::allow_log_reversion`]: `crate::config::Config::allow_log_reversion` + [`RaftLogStorage::save_committed()`]: `crate::storage::RaftLogStorage::save_committed` [`RaftNetwork`]: `crate::network::RaftNetwork` diff --git a/openraft/src/docs/feature_flags/feature-flags-toc.md b/openraft/src/docs/feature_flags/feature-flags-toc.md index c2fc31e55..0b71d9f1e 100644 --- a/openraft/src/docs/feature_flags/feature-flags-toc.md +++ b/openraft/src/docs/feature_flags/feature-flags-toc.md @@ -1,7 +1,6 @@ - [feature-flag `bench`](#feature-flag-bench) - [feature-flag `bt`](#feature-flag-bt) - [feature-flag `compat`](#feature-flag-compat) -- [feature-flag `loosen-follower-log-revert`](#feature-flag-loosen-follower-log-revert) - [feature-flag `serde`](#feature-flag-serde) - [feature-flag `single-term-leader`](#feature-flag-single-term-leader) - [feature-flag `singlethreaded`](#feature-flag-singlethreaded) diff --git a/openraft/src/docs/feature_flags/feature-flags.md b/openraft/src/docs/feature_flags/feature-flags.md index 1f83fc29f..2dba5e27a 100644 --- a/openraft/src/docs/feature_flags/feature-flags.md +++ b/openraft/src/docs/feature_flags/feature-flags.md @@ -17,15 +17,6 @@ This feature works ONLY with nightly rust, because it requires unstable feature Enables compatibility supporting types. -## feature-flag `loosen-follower-log-revert` - -Permit the follower's log to roll back to an earlier state without causing the leader to panic. -Although log state reversion is typically seen as a bug, enabling it can be useful for testing or other special scenarios. -For instance, in an even number nodes cluster, -erasing a node's data and then rebooting it(log reverts to empty) will not result in data loss. - -**Do not use it unless you know what you are doing**. - ## feature-flag `serde` Derives `serde::Serialize, serde::Deserialize` for type that are used diff --git a/openraft/src/engine/engine_config.rs b/openraft/src/engine/engine_config.rs index 04521eec2..2de3d3f2c 100644 --- a/openraft/src/engine/engine_config.rs +++ b/openraft/src/engine/engine_config.rs @@ -25,6 +25,8 @@ pub(crate) struct EngineConfig { /// The maximum number of entries per payload allowed to be transmitted during replication pub(crate) max_payload_entries: u64, + pub(crate) allow_log_reversion: bool, + pub(crate) timer_config: time_state::Config, } @@ -39,6 +41,8 @@ where C: RaftTypeConfig max_in_snapshot_log_to_keep: config.max_in_snapshot_log_to_keep, purge_batch_size: config.purge_batch_size, max_payload_entries: config.max_payload_entries, + allow_log_reversion: config.get_allow_log_reversion(), + timer_config: time_state::Config { election_timeout, smaller_log_timeout: Duration::from_millis(config.election_timeout_max * 2), @@ -55,6 +59,7 @@ where C: RaftTypeConfig max_in_snapshot_log_to_keep: 1000, purge_batch_size: 256, max_payload_entries: 300, + allow_log_reversion: false, timer_config: time_state::Config::default(), } } diff --git a/openraft/src/engine/handler/replication_handler/mod.rs b/openraft/src/engine/handler/replication_handler/mod.rs index 31b726403..7193c934d 100644 --- a/openraft/src/engine/handler/replication_handler/mod.rs +++ b/openraft/src/engine/handler/replication_handler/mod.rs @@ -9,6 +9,7 @@ use crate::engine::EngineOutput; use crate::engine::ReplicationProgress; use crate::error::NodeNotFound; use crate::error::Operation; +use crate::progress; use crate::progress::entry::ProgressEntry; use crate::progress::Inflight; use crate::progress::Progress; @@ -163,7 +164,9 @@ where C: RaftTypeConfig let quorum_accepted = self .leader .progress - .update_with(&node_id, |prog_entry| prog_entry.update_matching(log_id)) + .update_with(&node_id, |prog_entry| { + prog_entry.new_updater(&*self.config).update_matching(log_id) + }) .expect("it should always update existing progress") .clone(); @@ -215,7 +218,9 @@ where C: RaftTypeConfig let prog_entry = self.leader.progress.get_mut(&target).unwrap(); - prog_entry.update_conflicting(conflict.index); + let mut updater = progress::entry::update::Updater::new(self.config, prog_entry); + + updater.update_conflicting(conflict.index); } /// Enable one-time replication reset for a specific node upon log reversion detection. @@ -241,7 +246,7 @@ where C: RaftTypeConfig return Err(NodeNotFound::new(target, Operation::AllowNextRevert)); }; - prog_entry.reset_on_reversion = allow; + prog_entry.allow_log_reversion = allow; Ok(()) } diff --git a/openraft/src/engine/tests/startup_test.rs b/openraft/src/engine/tests/startup_test.rs index 7b60a93b5..3174e579a 100644 --- a/openraft/src/engine/tests/startup_test.rs +++ b/openraft/src/engine/tests/startup_test.rs @@ -78,7 +78,7 @@ fn test_startup_as_leader_without_logs() -> anyhow::Result<()> { matching: None, inflight: Inflight::None, searching_end: 4, - reset_on_reversion: false, + allow_log_reversion: false, })] }, Command::AppendInputEntries { @@ -130,7 +130,7 @@ fn test_startup_as_leader_with_proposed_logs() -> anyhow::Result<()> { matching: None, inflight: Inflight::None, searching_end: 7, - reset_on_reversion: false, + allow_log_reversion: false, })] }, Command::Replicate { diff --git a/openraft/src/lib.rs b/openraft/src/lib.rs index b1d01a359..2b05ff504 100644 --- a/openraft/src/lib.rs +++ b/openraft/src/lib.rs @@ -25,6 +25,12 @@ macro_rules! func_name { }}; } +#[cfg(feature = "loosen-follower-log-revert")] +compile_error!( + "The feature flag `loosen-follower-log-revert` is removed since `0.10.0`. \ + Use `Config::allow_log_reversion` instead." +); + pub extern crate openraft_macros; mod change_members; diff --git a/openraft/src/progress/entry/mod.rs b/openraft/src/progress/entry/mod.rs index 323893c01..2ae91de4d 100644 --- a/openraft/src/progress/entry/mod.rs +++ b/openraft/src/progress/entry/mod.rs @@ -1,3 +1,5 @@ +pub(crate) mod update; + use std::borrow::Borrow; use std::error::Error; use std::fmt::Debug; @@ -7,6 +9,8 @@ use std::fmt::Formatter; use validit::Validate; use crate::display_ext::DisplayOptionExt; +use crate::engine::EngineConfig; +use crate::progress::entry::update::Updater; use crate::progress::inflight::Inflight; use crate::raft_state::LogStateReader; use crate::LogId; @@ -37,7 +41,7 @@ where C: RaftTypeConfig /// to it. /// /// This flag will be cleared after the progress entry is reset. - pub(crate) reset_on_reversion: bool, + pub(crate) allow_log_reversion: bool, } impl ProgressEntry @@ -49,7 +53,7 @@ where C: RaftTypeConfig matching: matching.clone(), inflight: Inflight::None, searching_end: matching.next_index(), - reset_on_reversion: false, + allow_log_reversion: false, } } @@ -61,7 +65,7 @@ where C: RaftTypeConfig matching: None, inflight: Inflight::None, searching_end: end, - reset_on_reversion: false, + allow_log_reversion: false, } } @@ -74,6 +78,10 @@ where C: RaftTypeConfig self } + pub(crate) fn new_updater<'a>(&'a mut self, engine_config: &'a EngineConfig) -> Updater<'a, C> { + Updater::new(engine_config, self) + } + /// Return if a range of log id `..=log_id` is inflight sending. /// /// `prev_log_id` is never inflight. @@ -88,76 +96,6 @@ where C: RaftTypeConfig } } - pub(crate) fn update_matching(&mut self, matching: Option>) { - tracing::debug!( - self = display(&self), - matching = display(matching.display()), - "update_matching" - ); - - self.inflight.ack(matching.clone()); - - debug_assert!(matching >= self.matching); - self.matching = matching; - - let matching_next = self.matching.next_index(); - self.searching_end = std::cmp::max(self.searching_end, matching_next); - } - - /// Update conflicting log index. - /// - /// Conflicting log index is the last found log index on a follower that is not matching the - /// leader log. - /// - /// Usually if follower's data is lost, `conflict` is always greater than or equal `matching`. - /// But for testing purpose, a follower is allowed to clean its data and wait for leader to - /// replicate all data to it. - /// - /// To allow a follower to clean its data, enable feature flag [`loosen-follower-log-revert`] . - /// - /// [`loosen-follower-log-revert`]: crate::docs::feature_flags#feature_flag_loosen_follower_log_revert - pub(crate) fn update_conflicting(&mut self, conflict: u64) { - tracing::debug!(self = debug(&self), conflict = display(conflict), "update_conflict"); - - self.inflight.conflict(conflict); - - debug_assert!(conflict < self.searching_end); - self.searching_end = conflict; - - // An already matching log id is found lost: - // - // - If log reversion is allowed, just restart the binary search from the beginning. - // - Otherwise, panic it. - - let allow_reset = if cfg!(feature = "loosen-follower-log-revert") { - true - } else { - self.reset_on_reversion - }; - - if allow_reset { - if conflict < self.matching.next_index() { - tracing::warn!( - "conflict {} < last matching {}: follower log is reverted; with 'loosen-follower-log-revert' enabled, this is allowed.", - conflict, - self.matching.display(), - ); - - self.matching = None; - self.reset_on_reversion = false; - } - } else { - debug_assert!( - conflict >= self.matching.next_index(), - "follower log reversion is not allowed \ - without `--features loosen-follower-log-revert`; \ - matching: {}; conflict: {}", - self.matching.display(), - conflict - ); - } - } - /// Initialize a replication action: sending log entries or sending snapshot. /// /// If there is an action in progress, i.e., `inflight` is not None, it returns an `Err` diff --git a/openraft/src/progress/entry/tests.rs b/openraft/src/progress/entry/tests.rs index f528f4884..466e339db 100644 --- a/openraft/src/progress/entry/tests.rs +++ b/openraft/src/progress/entry/tests.rs @@ -1,6 +1,7 @@ use std::borrow::Borrow; use crate::engine::testing::UTConfig; +use crate::engine::EngineConfig; use crate::progress::entry::ProgressEntry; use crate::progress::inflight::Inflight; use crate::raft_state::LogStateReader; @@ -38,16 +39,18 @@ fn test_is_log_range_inflight() -> anyhow::Result<()> { #[test] fn test_update_matching() -> anyhow::Result<()> { + let engine_config = EngineConfig::new_default(1); + // Update matching and inflight { let mut pe = ProgressEntry::::empty(20); pe.inflight = inflight_logs(5, 10); - pe.update_matching(Some(log_id(6))); + pe.new_updater(&engine_config).update_matching(Some(log_id(6))); assert_eq!(inflight_logs(6, 10), pe.inflight); assert_eq!(Some(log_id(6)), pe.matching); assert_eq!(20, pe.searching_end); - pe.update_matching(Some(log_id(10))); + pe.new_updater(&engine_config).update_matching(Some(log_id(10))); assert_eq!(Inflight::None, pe.inflight); assert_eq!(Some(log_id(10)), pe.matching); assert_eq!(20, pe.searching_end); @@ -59,7 +62,7 @@ fn test_update_matching() -> anyhow::Result<()> { pe.matching = Some(log_id(6)); pe.inflight = inflight_logs(5, 20); - pe.update_matching(Some(log_id(20))); + pe.new_updater(&engine_config).update_matching(Some(log_id(20))); assert_eq!(21, pe.searching_end); } @@ -71,7 +74,10 @@ fn test_update_conflicting() -> anyhow::Result<()> { let mut pe = ProgressEntry::::empty(20); pe.matching = Some(log_id(3)); pe.inflight = inflight_logs(5, 10); - pe.update_conflicting(5); + + let engine_config = EngineConfig::new_default(1); + pe.new_updater(&engine_config).update_conflicting(5); + assert_eq!(Inflight::None, pe.inflight); assert_eq!(&Some(log_id(3)), pe.borrow()); assert_eq!(5, pe.searching_end); diff --git a/openraft/src/progress/entry/update.rs b/openraft/src/progress/entry/update.rs new file mode 100644 index 000000000..04f211699 --- /dev/null +++ b/openraft/src/progress/entry/update.rs @@ -0,0 +1,94 @@ +use crate::display_ext::DisplayOptionExt; +use crate::engine::EngineConfig; +use crate::progress::entry::ProgressEntry; +use crate::LogId; +use crate::LogIdOptionExt; +use crate::RaftTypeConfig; + +/// It implements updating operations for a [`ProgressEntry`] +pub(crate) struct Updater<'a, C> +where C: RaftTypeConfig +{ + engine_config: &'a EngineConfig, + entry: &'a mut ProgressEntry, +} + +impl<'a, C> Updater<'a, C> +where C: RaftTypeConfig +{ + pub(crate) fn new(engine_config: &'a EngineConfig, entry: &'a mut ProgressEntry) -> Self { + Self { engine_config, entry } + } + + /// Update conflicting log index. + /// + /// Conflicting log index is the last found log index on a follower that is not matching the + /// leader log. + /// + /// Usually if follower's data is not lost, `conflict` is always greater than or equal + /// `matching`. But for testing purpose, a follower is allowed to clean its data and wait + /// for leader to replicate all data to it. + /// + /// To allow a follower to clean its data, set the config [`Config::allow_log_reversion`] . + /// + /// [`Config::allow_log_reversion`]: `crate::config::Config::allow_log_reversion` + pub(crate) fn update_conflicting(&mut self, conflict: u64) { + tracing::debug!( + "update_conflict: current progress_entry: {}; conflict: {}", + self.entry, + conflict + ); + + self.entry.inflight.conflict(conflict); + + debug_assert!(conflict < self.entry.searching_end); + self.entry.searching_end = conflict; + + // An already matching log id is found lost: + // + // - If log reversion is allowed, just restart the binary search from the beginning. + // - Otherwise, panic it. + + let allow_reset = self.entry.allow_log_reversion || self.engine_config.allow_log_reversion; + + if allow_reset { + if conflict < self.entry.matching.next_index() { + tracing::warn!( + "conflict {} < last matching {}: \ + follower log is reverted; \ + with 'allow_log_reversion' enabled, this is allowed.", + conflict, + self.entry.matching.display(), + ); + + self.entry.matching = None; + self.entry.allow_log_reversion = false; + } + } else { + debug_assert!( + conflict >= self.entry.matching.next_index(), + "follower log reversion is not allowed \ + without `allow_log_reversion` enabled; \ + matching: {}; conflict: {}", + self.entry.matching.display(), + conflict + ); + } + } + + pub(crate) fn update_matching(&mut self, matching: Option>) { + tracing::debug!( + "update_matching: current progress_entry: {}; matching: {}", + self.entry, + matching.display() + ); + + self.entry.inflight.ack(matching.clone()); + + debug_assert!(matching >= self.entry.matching); + self.entry.matching = matching; + + let matching_next = self.entry.matching.next_index(); + self.entry.searching_end = std::cmp::max(self.entry.searching_end, matching_next); + } +} diff --git a/openraft/src/raft/trigger.rs b/openraft/src/raft/trigger.rs index f1637230a..c84173d9c 100644 --- a/openraft/src/raft/trigger.rs +++ b/openraft/src/raft/trigger.rs @@ -9,7 +9,7 @@ use crate::RaftTypeConfig; /// Trigger is an interface to trigger an action to RaftCore by external caller. /// -/// It is create with [`Raft::trigger()`]. +/// It is created with [`Raft::trigger()`]. /// /// For example, to trigger an election at once, you can use the following code /// ```ignore @@ -111,8 +111,7 @@ where C: RaftTypeConfig /// /// ### Automatic Replication Reset /// - /// When the [`loosen-follower-log-revert`](`crate::docs::feature_flags# - /// feature-flag-loosen-follower-log-revert) feature flag is enabled, the Leader automatically + /// When the [`Config::allow_log_reversion`] 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. /// @@ -126,6 +125,8 @@ where C: RaftTypeConfig /// - call [`Self::allow_next_revert`] on the Leader. /// - Clear the target node's data directory. /// - Restart the target node. + /// + /// [`Config::allow_log_reversion`]: `crate::Config::allow_log_reversion` pub async fn allow_next_revert( &self, to: &C::NodeId, diff --git a/openraft/src/vote/ref_vote.rs b/openraft/src/vote/ref_vote.rs index 1c5148606..5024aed93 100644 --- a/openraft/src/vote/ref_vote.rs +++ b/openraft/src/vote/ref_vote.rs @@ -5,6 +5,8 @@ use crate::LeaderId; use crate::NodeId; /// Same as [`Vote`] but with a reference to the [`LeaderId`]. +/// +/// [`Vote`]: crate::vote::Vote #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct RefVote<'a, NID: NodeId> { pub(crate) leader_id: &'a LeaderId, diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 5336db22a..7ecef62c2 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -41,4 +41,3 @@ tracing-subscriber = { workspace = true } bt = ["openraft/bt"] single-term-leader = ["openraft/single-term-leader"] -loosen-follower-log-revert = ["openraft/loosen-follower-log-revert"] diff --git a/tests/tests/replication/main.rs b/tests/tests/replication/main.rs index 76bf870e3..a17e4f8c4 100644 --- a/tests/tests/replication/main.rs +++ b/tests/tests/replication/main.rs @@ -8,6 +8,5 @@ mod t10_append_entries_partial_success; mod t50_append_entries_backoff; mod t50_append_entries_backoff_rejoin; mod t51_append_entries_too_large; -#[cfg(feature = "loosen-follower-log-revert")] mod t60_feature_loosen_follower_log_revert; mod t61_allow_follower_log_revert; diff --git a/tests/tests/replication/t60_feature_loosen_follower_log_revert.rs b/tests/tests/replication/t60_feature_loosen_follower_log_revert.rs index 02d9c6853..22b3f5edb 100644 --- a/tests/tests/replication/t60_feature_loosen_follower_log_revert.rs +++ b/tests/tests/replication/t60_feature_loosen_follower_log_revert.rs @@ -8,7 +8,7 @@ use openraft::Config; use crate::fixtures::ut_harness; use crate::fixtures::RaftRouter; -/// With "--features loosen-follower-log-revert", the leader allows follower to revert its log to an +/// With "allow_log_reversion", the leader allows follower to revert its log to an /// earlier state. #[tracing::instrument] #[test_harness::test(harness = ut_harness)] @@ -19,6 +19,7 @@ async fn feature_loosen_follower_log_revert() -> Result<()> { enable_heartbeat: false, // Make sure the replication is done in more than one steps max_payload_entries: 1, + allow_log_reversion: Some(true), ..Default::default() } .validate()?,