nodedb_cluster/multi_raft/
membership.rs1use nodedb_raft::NodeRole;
19
20use crate::error::{ClusterError, Result};
21
22use super::core::MultiRaft;
23
24impl MultiRaft {
25 pub fn group_contains_node(&self, group_id: u64, node_id: u64) -> Option<bool> {
27 let membership = self.group_membership(group_id)?;
28 Some(membership.voters.contains(&node_id) || membership.learners.contains(&node_id))
29 }
30
31 pub fn commit_index_for(&self, group_id: u64) -> Option<u64> {
34 self.groups.get(&group_id).map(|n| n.commit_index())
35 }
36
37 pub fn ready_learners(&self, group_id: u64) -> Vec<u64> {
43 let Some(node) = self.groups.get(&group_id) else {
44 return Vec::new();
45 };
46 if node.role() != NodeRole::Leader {
47 return Vec::new();
48 }
49 let commit = node.commit_index();
50 node.learners()
51 .iter()
52 .copied()
53 .filter(|&learner| node.match_index_for(learner).unwrap_or(0) >= commit)
54 .collect()
55 }
56
57 pub fn group_leader(&self, group_id: u64) -> u64 {
59 self.groups
60 .get(&group_id)
61 .map(|n| n.leader_id())
62 .unwrap_or(0)
63 }
64
65 pub fn group_role_is_leader(&self, group_id: u64) -> bool {
67 self.groups
68 .get(&group_id)
69 .map(|n| n.role() == NodeRole::Leader)
70 .unwrap_or(false)
71 }
72
73 pub fn transfer_leadership(&mut self, group_id: u64, target: u64) -> Result<()> {
80 let node = self
81 .groups
82 .get_mut(&group_id)
83 .ok_or(ClusterError::GroupNotFound { group_id })?;
84 node.transfer_leadership(target).map_err(ClusterError::Raft)
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use std::time::{Duration, Instant};
91
92 use super::*;
93 use crate::routing::RoutingTable;
94
95 fn make_multi_raft_single_node(node_id: u64) -> MultiRaft {
96 let dir = tempfile::tempdir().unwrap();
97 let rt = RoutingTable::uniform(1, &[node_id], 1);
98 let mut mr = MultiRaft::new(node_id, rt, dir.path().to_path_buf());
99 mr.add_group(0, vec![]).unwrap();
100 mr
101 }
102
103 #[test]
104 fn transfer_leadership_group_not_found() {
105 let mut mr = make_multi_raft_single_node(1);
106 let err = mr.transfer_leadership(999, 2).unwrap_err();
107 assert!(
108 matches!(err, ClusterError::GroupNotFound { group_id: 999 }),
109 "expected GroupNotFound, got {err:?}"
110 );
111 }
112
113 #[test]
114 fn transfer_leadership_delegates_to_raft_node() {
115 let mut mr = make_multi_raft_single_node(1);
116 if let Some(node) = mr.groups_mut().get_mut(&0) {
118 node.election_deadline_override(Instant::now() - Duration::from_millis(1));
119 node.tick();
120 }
122 let err = mr.transfer_leadership(0, 1).unwrap_err();
125 assert!(
126 matches!(err, ClusterError::Raft(_)),
127 "expected Raft error from transfer_leadership, got {err:?}"
128 );
129 }
130}