use std::fmt;
use display_more::DisplayOptionExt;
use display_more::DisplaySliceExt;
use crate::RaftTypeConfig;
use crate::entry::RaftEntry;
use crate::log_id_range::LogIdRange;
use crate::type_config::alias::LogIdOf;
use crate::type_config::alias::VoteOf;
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
pub struct AppendEntriesRequest<C: RaftTypeConfig> {
pub vote: VoteOf<C>,
pub prev_log_id: Option<LogIdOf<C>>,
pub entries: Vec<C::Entry>,
pub leader_commit: Option<LogIdOf<C>>,
}
impl<C: RaftTypeConfig> fmt::Debug for AppendEntriesRequest<C> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("AppendEntriesRequest")
.field("vote", &self.vote)
.field("prev_log_id", &self.prev_log_id)
.field("entries", &self.entries)
.field("leader_commit", &self.leader_commit)
.finish()
}
}
impl<C> fmt::Display for AppendEntriesRequest<C>
where C: RaftTypeConfig
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"vote={}, prev_log_id={}, leader_commit={}, entries={}",
self.vote,
self.prev_log_id.display(),
self.leader_commit.display(),
self.entries.display()
)
}
}
impl<C> AppendEntriesRequest<C>
where C: RaftTypeConfig
{
pub(crate) fn last_log_id(&self) -> Option<LogIdOf<C>> {
self.entries.last().map(|e| e.log_id()).or(self.prev_log_id.clone())
}
pub(crate) fn log_id_range(&self) -> LogIdRange<C> {
LogIdRange::new(self.prev_log_id.clone(), self.last_log_id())
}
}
#[cfg(test)]
mod tests {
use crate::Vote;
use crate::engine::testing::UTConfig;
use crate::engine::testing::log_id;
use crate::raft::AppendEntriesRequest;
use crate::testing::blank_ent;
fn req(prev: Option<u64>, entries: Vec<u64>) -> AppendEntriesRequest<UTConfig> {
AppendEntriesRequest {
vote: Vote::new_committed(1, 1),
prev_log_id: prev.map(|i| log_id(1, 1, i)),
entries: entries.into_iter().map(|i| blank_ent::<UTConfig>(1, 1, i)).collect(),
leader_commit: None,
}
}
#[test]
fn test_last_log_id() {
assert_eq!(req(None, vec![]).last_log_id(), None);
assert_eq!(req(Some(5), vec![]).last_log_id(), Some(log_id(1, 1, 5)));
assert_eq!(req(None, vec![1, 2]).last_log_id(), Some(log_id(1, 1, 2)));
assert_eq!(req(Some(5), vec![6, 7]).last_log_id(), Some(log_id(1, 1, 7)));
}
#[test]
fn test_log_id_range() {
let r = req(None, vec![]).log_id_range();
assert_eq!((r.prev, r.last), (None, None));
let r = req(Some(5), vec![]).log_id_range();
assert_eq!((r.prev, r.last), (Some(log_id(1, 1, 5)), Some(log_id(1, 1, 5))));
let r = req(None, vec![1, 2]).log_id_range();
assert_eq!((r.prev, r.last), (None, Some(log_id(1, 1, 2))));
let r = req(Some(5), vec![6, 7]).log_id_range();
assert_eq!((r.prev, r.last), (Some(log_id(1, 1, 5)), Some(log_id(1, 1, 7))));
}
}