actix-raft/async-raft/tests/compaction.rs

97 lines
3.2 KiB
Rust

mod fixtures;
use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
use async_raft::raft::MembershipConfig;
use async_raft::{Config, SnapshotPolicy};
use maplit::hashset;
use tokio::time::delay_for;
use fixtures::RaftRouter;
/// Compaction test.
///
/// What does this test do?
///
/// - build a stable single node cluster.
/// - send enough requests to the node that log compaction will be triggered.
/// - add new nodes and assert that they receive the snapshot.
///
/// RUST_LOG=async_raft,memstore,compaction=trace cargo test -p async-raft --test compaction
#[tokio::test(core_threads = 4)]
async fn compaction() -> Result<()> {
fixtures::init_tracing();
// Setup test dependencies.
let config = Arc::new(
Config::build("test".into())
.snapshot_policy(SnapshotPolicy::LogsSinceLast(500))
.validate()
.expect("failed to build Raft config"),
);
let router = Arc::new(RaftRouter::new(config.clone()));
router.new_raft_node(0).await;
// Assert all nodes are in non-voter state & have no entries.
delay_for(Duration::from_secs(10)).await;
router.assert_pristine_cluster().await;
// Initialize the cluster, then assert that a stable cluster was formed & held.
tracing::info!("--- initializing cluster");
router.initialize_from_single_node(0).await?;
delay_for(Duration::from_secs(10)).await;
router.assert_stable_cluster(Some(1), Some(1)).await;
// Send enough requests to the cluster that compaction on the node should be triggered.
router.client_request_many(0, "0", 499).await; // Puts us exactly at the configured snapshot policy threshold.
delay_for(Duration::from_secs(5)).await; // Wait to ensure there is enough time for a snapshot to be built (this is way more than enough).
router.assert_stable_cluster(Some(1), Some(500)).await;
router
.assert_storage_state(
1,
500,
Some(0),
500,
Some((
500.into(),
1,
MembershipConfig {
members: hashset![0],
members_after_consensus: None,
},
)),
)
.await;
// Add a new node and assert that it received the same snapshot.
router.new_raft_node(1).await;
router.add_non_voter(0, 1).await.expect("failed to add new node as non-voter");
router
.change_membership(0, hashset![0, 1])
.await
.expect("failed to modify cluster membership");
delay_for(Duration::from_secs(5)).await; // Wait to ensure metrics are updated (this is way more than enough).
router.assert_stable_cluster(Some(1), Some(502)).await; // We expect index to be 500 + 2 (joint & uniform config change entries).
router
.assert_storage_state(
1,
502,
None,
500,
Some((
500.into(),
1,
MembershipConfig {
members: hashset![0u64],
members_after_consensus: None,
},
)),
)
.await;
// -------------------------------- ^^^^ this value is None because non-voters do not vote.
Ok(())
}