Skip to main content

amaters_cluster/
error.rs

1//! Error types for the Raft consensus module
2
3use std::fmt;
4
5/// Result type for Raft operations
6pub type RaftResult<T> = Result<T, RaftError>;
7
8/// Errors that can occur during Raft consensus operations
9#[derive(Debug, Clone, PartialEq)]
10pub enum RaftError {
11    /// Node is not the leader
12    NotLeader {
13        /// Current leader ID if known
14        leader_id: Option<u64>,
15    },
16    /// Invalid node state for this operation
17    InvalidState {
18        /// Expected state
19        expected: String,
20        /// Actual state
21        actual: String,
22    },
23    /// Log inconsistency detected
24    LogInconsistency {
25        /// Description of the inconsistency
26        reason: String,
27    },
28    /// Storage operation failed
29    StorageError {
30        /// Error message
31        message: String,
32    },
33    /// Term is stale
34    StaleTerm {
35        /// Current term
36        current: u64,
37        /// Received term
38        received: u64,
39    },
40    /// Vote already granted to another candidate
41    VoteAlreadyGranted {
42        /// Node that received the vote
43        voted_for: u64,
44    },
45    /// Configuration error
46    ConfigError {
47        /// Error message
48        message: String,
49    },
50    /// Network error
51    NetworkError {
52        /// Error message
53        message: String,
54    },
55    /// Timeout occurred
56    Timeout {
57        /// Timeout description
58        description: String,
59    },
60    /// A membership change is already in progress (joint consensus active)
61    MembershipChangeInProgress,
62    /// The target node is already a member of the cluster
63    NodeAlreadyMember {
64        /// The node ID that is already a member
65        node_id: u64,
66    },
67    /// The target node is not a member of the cluster
68    NodeNotMember {
69        /// The node ID that was not found
70        node_id: u64,
71    },
72    /// State machine application error
73    StateMachineError {
74        /// Error message
75        message: String,
76    },
77    /// Node is currently replaying its WAL on startup and cannot serve requests
78    Recovering,
79    /// Generic error
80    Other {
81        /// Error message
82        message: String,
83    },
84}
85
86impl fmt::Display for RaftError {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        match self {
89            RaftError::NotLeader { leader_id } => {
90                write!(f, "Not leader")?;
91                if let Some(id) = leader_id {
92                    write!(f, " (current leader: {})", id)?;
93                }
94                Ok(())
95            }
96            RaftError::InvalidState { expected, actual } => {
97                write!(f, "Invalid state: expected {}, got {}", expected, actual)
98            }
99            RaftError::LogInconsistency { reason } => {
100                write!(f, "Log inconsistency: {}", reason)
101            }
102            RaftError::StorageError { message } => {
103                write!(f, "Storage error: {}", message)
104            }
105            RaftError::StaleTerm { current, received } => {
106                write!(f, "Stale term: current {}, received {}", current, received)
107            }
108            RaftError::VoteAlreadyGranted { voted_for } => {
109                write!(f, "Vote already granted to node {}", voted_for)
110            }
111            RaftError::ConfigError { message } => {
112                write!(f, "Configuration error: {}", message)
113            }
114            RaftError::NetworkError { message } => {
115                write!(f, "Network error: {}", message)
116            }
117            RaftError::Timeout { description } => {
118                write!(f, "Timeout: {}", description)
119            }
120            RaftError::MembershipChangeInProgress => {
121                write!(
122                    f,
123                    "A membership change is already in progress (joint consensus active)"
124                )
125            }
126            RaftError::NodeAlreadyMember { node_id } => {
127                write!(f, "Node {} is already a member of the cluster", node_id)
128            }
129            RaftError::NodeNotMember { node_id } => {
130                write!(f, "Node {} is not a member of the cluster", node_id)
131            }
132            RaftError::StateMachineError { message } => {
133                write!(f, "State machine error: {}", message)
134            }
135            RaftError::Recovering => {
136                write!(
137                    f,
138                    "Node is replaying WAL on startup and cannot serve requests"
139                )
140            }
141            RaftError::Other { message } => {
142                write!(f, "Error: {}", message)
143            }
144        }
145    }
146}
147
148impl std::error::Error for RaftError {}