use std::fmt;
use display_more::DisplayOptionExt;
use crate::RaftTypeConfig;
use crate::raft::StreamAppendError;
use crate::raft::stream_append::StreamAppendResult;
use crate::type_config::alias::LogIdOf;
use crate::type_config::alias::VoteOf;
#[derive(Debug, Clone)]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
pub enum AppendEntriesResponse<C: RaftTypeConfig> {
Success,
PartialSuccess(Option<LogIdOf<C>>),
Conflict,
HigherVote(VoteOf<C>),
}
impl<C> AppendEntriesResponse<C>
where C: RaftTypeConfig
{
pub fn is_success(&self) -> bool {
matches!(*self, AppendEntriesResponse::Success)
}
pub(crate) fn get_partial_success(&self) -> Option<&Option<LogIdOf<C>>> {
match self {
AppendEntriesResponse::PartialSuccess(log_id) => Some(log_id),
_ => None,
}
}
pub fn is_conflict(&self) -> bool {
matches!(*self, AppendEntriesResponse::Conflict)
}
pub fn into_stream_result(
self,
prev_log_id: Option<LogIdOf<C>>,
last_log_id: Option<LogIdOf<C>>,
) -> StreamAppendResult<C> {
match self {
AppendEntriesResponse::Success => Ok(last_log_id),
AppendEntriesResponse::PartialSuccess(log_id) => Ok(log_id),
AppendEntriesResponse::Conflict => Err(StreamAppendError::Conflict(prev_log_id.unwrap())),
AppendEntriesResponse::HigherVote(vote) => Err(StreamAppendError::HigherVote(vote)),
}
}
}
impl<C: RaftTypeConfig> From<StreamAppendResult<C>> for AppendEntriesResponse<C> {
fn from(r: StreamAppendResult<C>) -> Self {
match r {
Ok(_) => AppendEntriesResponse::Success,
Err(StreamAppendError::Conflict(_)) => AppendEntriesResponse::Conflict,
Err(StreamAppendError::HigherVote(v)) => AppendEntriesResponse::HigherVote(v),
}
}
}
impl<C> fmt::Display for AppendEntriesResponse<C>
where C: RaftTypeConfig
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AppendEntriesResponse::Success => write!(f, "Success"),
AppendEntriesResponse::PartialSuccess(m) => {
write!(f, "PartialSuccess({})", m.display())
}
AppendEntriesResponse::HigherVote(vote) => write!(f, "Higher vote, {}", vote),
AppendEntriesResponse::Conflict => write!(f, "Conflict"),
}
}
}