use std::ops::RangeInclusive;
use async_trait::async_trait;
use num_traits::{Bounded, Zero};
use thiserror::Error;
use crate::error::BoxError;
use crate::RoundNum;
#[derive(Debug)]
pub struct AppendArgs<R: RoundNum> {
pub round: RangeInclusive<R>,
pub importance: Importance,
pub retry_policy: Box<dyn RetryPolicy>,
}
impl<R: RoundNum> Default for AppendArgs<R> {
fn default() -> Self {
Self {
round: Zero::zero()..=Bounded::max_value(),
importance: Importance::GainLeadership,
retry_policy: Box::new(DoNotRetry),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Importance {
GainLeadership,
MaintainLeadership(Peeryness),
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Peeryness {
Peery,
Unpeery,
}
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum AppendError {
#[error("append was aborted")]
Aborted(BoxError),
#[error("round had already converged")]
Converged,
#[error("node is disoriented")]
Disoriented,
#[error("node was removed from the cluster")]
Exiled,
#[error("node lost its mandate or failed in acquiring one")]
Lost,
#[error("node could not achieve a quorum")]
NoQuorum,
#[error("I/O error")]
IoError(crate::error::IoError),
#[error("uncategorized error occured")]
Other(crate::error::BoxError),
#[error("node is passive")]
Passive,
#[error("node was forced to append a different entry")]
Railroaded,
#[error("node is shut down")]
ShutDown,
#[error("node is stalled")]
Stalled,
}
#[async_trait]
pub trait RetryPolicy: std::fmt::Debug + Send {
async fn eval(&mut self, err: AppendError) -> Result<(), BoxError>;
}
#[derive(Clone, Copy, Debug)]
pub struct DoNotRetry;
#[async_trait]
impl RetryPolicy for DoNotRetry {
async fn eval(&mut self, _err: AppendError) -> Result<(), BoxError> {
Err(Box::new(AbortedError))
}
}
#[derive(Clone, Debug, Error)]
#[error("append was aborted")]
pub struct AbortedError;