diff --git a/openraft/src/lib.rs b/openraft/src/lib.rs index 3f63c0dd0..5bc1d67dc 100644 --- a/openraft/src/lib.rs +++ b/openraft/src/lib.rs @@ -71,6 +71,7 @@ mod runtime; mod try_as_ref; #[cfg(test)] mod raft_state_test; +#[cfg(test)] mod rust_state_validate_test; pub use anyerror; pub use anyerror::AnyError; diff --git a/openraft/src/raft_state.rs b/openraft/src/raft_state.rs index 8c1cd1da6..0b1678b84 100644 --- a/openraft/src/raft_state.rs +++ b/openraft/src/raft_state.rs @@ -218,7 +218,14 @@ where } less_equal!(self.last_purged_log_id(), self.purge_upto()); - less_equal!(self.purge_upto(), self.snapshot_last_log_id()); + if self.snapshot_last_log_id().is_none() { + // There is no snapshot, it is possible the application does not store snapshot, and + // just restarted. it is just ok. + // In such a case, we assert the monotonic relation without snapshot-last-log-id + less_equal!(self.purge_upto(), self.committed()); + } else { + less_equal!(self.purge_upto(), self.snapshot_last_log_id()); + } less_equal!(self.snapshot_last_log_id(), self.committed()); less_equal!(self.committed(), self.last_log_id()); diff --git a/openraft/src/rust_state_validate_test.rs b/openraft/src/rust_state_validate_test.rs new file mode 100644 index 000000000..e085a8000 --- /dev/null +++ b/openraft/src/rust_state_validate_test.rs @@ -0,0 +1,32 @@ +use crate::engine::LogIdList; +use crate::validate::Validate; +use crate::CommittedLeaderId; +use crate::LogId; +use crate::RaftState; +use crate::SnapshotMeta; + +fn log_id(term: u64, index: u64) -> LogId { + LogId:: { + leader_id: CommittedLeaderId::new(term, 0), + index, + } +} + +#[test] +fn test_raft_state_validate_snapshot_is_none() -> anyhow::Result<()> { + // Some app does not persist snapshot, when restarted, purged is not None but snapshot_last_log_id + // is None. This is a valid state and should not emit error. + + let rs = RaftState:: { + log_ids: LogIdList::new(vec![log_id(1, 1), log_id(3, 4)]), + purged_next: 2, + purge_upto: Some(log_id(1, 1)), + committed: Some(log_id(1, 1)), + snapshot_meta: SnapshotMeta::default(), + ..Default::default() + }; + + assert!(rs.validate().is_ok()); + + Ok(()) +}