mod allow_next_revert_error;
mod conflicting_log_id;
pub mod decompose;
mod error_source;
mod fatal;
pub(crate) mod higher_vote;
pub mod into_ok;
pub(crate) mod into_raft_result;
mod leader_changed;
mod linearizable_read_error;
mod membership_error;
mod node_not_found;
mod operation;
mod raft_error;
mod reject_append_entries;
mod reject_vote;
mod replication_closed;
pub(crate) mod replication_error;
pub(crate) mod storage_error;
mod storage_io_result;
mod streaming_error;
use std::collections::BTreeSet;
use std::error::Error;
use std::time::Duration;
use openraft_macros::since;
pub use self::allow_next_revert_error::AllowNextRevertError;
pub use self::conflicting_log_id::ConflictingLogId;
pub use self::error_source::BacktraceDisplay;
pub use self::error_source::ErrorSource;
pub use self::fatal::Fatal;
pub(crate) use self::higher_vote::HigherVote;
pub use self::leader_changed::LeaderChanged;
pub use self::linearizable_read_error::LinearizableReadError;
pub use self::membership_error::MembershipError;
pub use self::node_not_found::NodeNotFound;
pub use self::operation::Operation;
pub use self::raft_error::RaftError;
pub(crate) use self::reject_append_entries::RejectAppendEntries;
pub use self::reject_vote::RejectVote;
pub use self::replication_closed::ReplicationClosed;
pub(crate) use self::replication_error::ReplicationError;
pub(crate) use self::storage_io_result::StorageIOResult;
pub use self::streaming_error::StreamingError;
use crate::LogId;
use crate::Membership;
use crate::RaftTypeConfig;
use crate::network::RPCTypes;
use crate::node::NodeId;
use crate::raft_types::SnapshotSegmentId;
use crate::try_as_ref::TryAsRef;
use crate::type_config::alias::CommittedLeaderIdOf;
use crate::type_config::alias::LogIdOf;
use crate::type_config::alias::VoteOf;
use crate::vote::RaftCommittedLeaderId;
#[deprecated(since = "0.10.0", note = "use `LinearizableReadError` instead")]
pub type CheckIsLeaderError<C> = LinearizableReadError<C>;
#[derive(Debug, Clone, thiserror::Error, derive_more::TryInto)]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum InstallSnapshotError {
#[error(transparent)]
SnapshotMismatch(#[from] SnapshotMismatch),
}
#[derive(Debug, Clone, thiserror::Error, derive_more::TryInto)]
#[derive(PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
pub enum ClientWriteError<C>
where C: RaftTypeConfig
{
#[error(transparent)]
ForwardToLeader(#[from] ForwardToLeader<C>),
#[error(transparent)]
ChangeMembershipError(#[from] ChangeMembershipError<CommittedLeaderIdOf<C>, C::NodeId>),
}
impl<C> TryAsRef<ForwardToLeader<C>> for ClientWriteError<C>
where C: RaftTypeConfig
{
fn try_as_ref(&self) -> Option<&ForwardToLeader<C>> {
match self {
Self::ForwardToLeader(f) => Some(f),
_ => None,
}
}
}
#[since(
version = "0.10.0",
change = "from `ChangeMembershipError<C>` to `ChangeMembershipError<CLID, NID>`"
)]
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
pub enum ChangeMembershipError<CLID, NID>
where
CLID: RaftCommittedLeaderId,
NID: NodeId,
{
#[error(transparent)]
InProgress(#[from] InProgress<CLID>),
#[error(transparent)]
EmptyMembership(#[from] EmptyMembership),
#[error(transparent)]
LearnerNotFound(#[from] LearnerNotFound<NID>),
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, derive_more::TryInto)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
pub enum InitializeError<C>
where C: RaftTypeConfig
{
#[error(transparent)]
NotAllowed(#[from] NotAllowed<C>),
#[error(transparent)]
NotInMembers(#[from] NotInMembers<C>),
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(bound(serialize = "E: serde::Serialize")),
serde(bound(deserialize = "E: for <'d> serde::Deserialize<'d>"))
)]
pub enum RPCError<C: RaftTypeConfig, E: Error = Infallible> {
#[error(transparent)]
Timeout(#[from] Timeout<C>),
#[error(transparent)]
Unreachable(#[from] Unreachable<C>),
#[error(transparent)]
Network(#[from] NetworkError<C>),
#[error(transparent)]
RemoteError(#[from] RemoteError<C, E>),
}
impl<C, E> RPCError<C, E>
where
C: RaftTypeConfig,
E: Error,
{
pub(crate) fn backoff_rank(&self) -> u64 {
match &self {
RPCError::Timeout(_) => 2,
RPCError::Unreachable(_unreachable) => 100,
RPCError::Network(_) => 2,
RPCError::RemoteError(_) => 100,
}
}
}
impl<C, E> RPCError<C, RaftError<C, E>>
where
C: RaftTypeConfig,
E: Error,
{
pub fn forward_to_leader(&self) -> Option<&ForwardToLeader<C>>
where E: TryAsRef<ForwardToLeader<C>> {
match self {
RPCError::Timeout(_) => None,
RPCError::Unreachable(_) => None,
RPCError::Network(_) => None,
RPCError::RemoteError(remote_err) => remote_err.source.forward_to_leader(),
}
}
}
impl<C> RPCError<C>
where C: RaftTypeConfig
{
pub fn with_raft_error<E: Error>(self) -> RPCError<C, RaftError<C, E>> {
match self {
RPCError::Timeout(e) => RPCError::Timeout(e),
RPCError::Unreachable(e) => RPCError::Unreachable(e),
RPCError::Network(e) => RPCError::Network(e),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[error("error occur on remote peer {target}: {source}")]
pub struct RemoteError<C, T: Error>
where C: RaftTypeConfig
{
#[cfg_attr(feature = "serde", serde(bound = ""))]
pub target: C::NodeId,
#[cfg_attr(feature = "serde", serde(bound = ""))]
pub target_node: Option<C::Node>,
pub source: T,
}
impl<C: RaftTypeConfig, T: Error> RemoteError<C, T> {
pub fn new(target: C::NodeId, e: T) -> Self {
Self {
target,
target_node: None,
source: e,
}
}
pub fn new_with_node(target: C::NodeId, node: C::Node, e: T) -> Self {
Self {
target,
target_node: Some(node),
source: e,
}
}
}
impl<C, E> From<RemoteError<C, Fatal<C>>> for RemoteError<C, RaftError<C, E>>
where
C: RaftTypeConfig,
E: Error,
{
fn from(e: RemoteError<C, Fatal<C>>) -> Self {
RemoteError {
target: e.target,
target_node: e.target_node,
source: RaftError::Fatal(e.source),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("NetworkError: {source}")]
pub struct NetworkError<C: RaftTypeConfig> {
source: C::ErrorSource,
}
impl<C: RaftTypeConfig> NetworkError<C> {
pub fn new<E: Error + 'static>(e: &E) -> Self {
Self {
source: C::ErrorSource::from_error(e),
}
}
pub fn from_string(msg: impl ToString) -> Self {
Self {
source: C::ErrorSource::from_string(msg),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("Unreachable node: {source}")]
pub struct Unreachable<C: RaftTypeConfig> {
source: C::ErrorSource,
}
impl<C: RaftTypeConfig> Unreachable<C> {
pub fn new<E: Error + 'static>(e: &E) -> Self {
Self {
source: C::ErrorSource::from_error(e),
}
}
pub fn from_string(msg: impl ToString) -> Self {
Self {
source: C::ErrorSource::from_string(msg),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("timeout after {timeout:?} when {action} {id}->{target}")]
pub struct Timeout<C: RaftTypeConfig> {
pub action: RPCTypes,
pub id: C::NodeId,
pub target: C::NodeId,
pub timeout: Duration,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("has to forward request to: {leader_id:?}, {leader_node:?}")]
pub struct ForwardToLeader<C>
where C: RaftTypeConfig
{
pub leader_id: Option<C::NodeId>,
pub leader_node: Option<C::Node>,
}
impl<C> ForwardToLeader<C>
where C: RaftTypeConfig
{
pub const fn empty() -> Self {
Self {
leader_id: None,
leader_node: None,
}
}
pub fn new(leader_id: C::NodeId, node: C::Node) -> Self {
Self {
leader_id: Some(leader_id),
leader_node: Some(node),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[error("snapshot segment id mismatch, expect: {expect}, got: {got}")]
pub struct SnapshotMismatch {
pub expect: SnapshotSegmentId,
pub got: SnapshotSegmentId,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("not enough for a quorum, cluster: {cluster}, got: {got:?}")]
pub struct QuorumNotEnough<C: RaftTypeConfig> {
pub cluster: String,
pub got: BTreeSet<C::NodeId>,
}
#[since(version = "0.10.0", change = "from `InProgress<C>` to `InProgress<CLID>`")]
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error(
"the cluster is already undergoing a configuration change at log {membership_log_id:?}, last committed membership log id: {committed:?}"
)]
pub struct InProgress<CLID>
where CLID: RaftCommittedLeaderId
{
pub committed: Option<LogId<CLID>>,
pub membership_log_id: Option<LogId<CLID>>,
}
#[since(version = "0.10.0", change = "removed `C: RaftTypeConfig` generic parameter")]
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("Learner {node_id} not found: add it as learner before adding it as a voter")]
pub struct LearnerNotFound<NID>
where NID: NodeId
{
pub node_id: NID,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("not allowed to initialize due to current raft state: last_log_id: {last_log_id:?} vote: {vote}")]
pub struct NotAllowed<C: RaftTypeConfig> {
pub last_log_id: Option<LogIdOf<C>>,
pub vote: VoteOf<C>,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize), serde(bound = ""))]
#[error("node {node_id} has to be a member. membership:{membership:?}")]
pub struct NotInMembers<C>
where C: RaftTypeConfig
{
pub node_id: C::NodeId,
pub membership: Membership<C::NodeId, C::Node>,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[error("new membership cannot be empty")]
pub struct EmptyMembership {}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[error("infallible")]
pub enum Infallible {}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[error("no-forward")]
pub enum NoForward {}