pub struct RaftNode<L: RaftLog = MemoryLog> { /* private fields */ }Expand description
A node in a Raft cluster: the deterministic consensus state machine.
Create one with new (Tier 1, in-memory log) or
with_log (Tier 3, your own RaftLog), then drive
it with step. The generic L defaults to MemoryLog,
so the common case never has to name it.
§Examples
use raft_io::{Event, RaftConfig, RaftNode};
let mut node = RaftNode::new(RaftConfig::single(1));
assert!(!node.is_leader());
while !node.is_leader() {
let _ = node.step(Event::Tick).unwrap();
}
assert!(node.is_leader());Implementations§
Source§impl RaftNode<MemoryLog>
impl RaftNode<MemoryLog>
Sourcepub fn new(config: RaftConfig) -> Self
pub fn new(config: RaftConfig) -> Self
Creates a node from config backed by an in-memory MemoryLog.
This is the Tier-1 entry point: one call, no generic to name, no I/O to
wire up. The node starts as a Follower in term 0.
§Examples
use raft_io::{RaftConfig, RaftNode, Role};
let node = RaftNode::new(RaftConfig::new(1, [2, 3]));
assert_eq!(node.role(), Role::Follower);
assert_eq!(node.term(), 0);Source§impl<L: RaftLog> RaftNode<L>
impl<L: RaftLog> RaftNode<L>
Sourcepub fn with_log(config: RaftConfig, log: L) -> Self
pub fn with_log(config: RaftConfig, log: L) -> Self
Creates a node from config backed by a caller-supplied log.
This is the Tier-3 entry point: provide any RaftLog implementation —
for example a durable, wal-db-backed store (v0.4). The node adopts
the log’s persisted HardState on construction, so a
store recovered from disk resumes in the term it last persisted and with
the vote it last cast.
§Examples
use raft_io::{MemoryLog, RaftConfig, RaftNode};
let node = RaftNode::with_log(RaftConfig::single(1), MemoryLog::new());
assert_eq!(node.id(), 1);Sourcepub fn is_leader(&self) -> bool
pub fn is_leader(&self) -> bool
Returns true if the node is the leader.
§Examples
use raft_io::{Event, RaftConfig, RaftNode};
let mut node = RaftNode::new(RaftConfig::single(1));
while !node.is_leader() {
let _ = node.step(Event::Tick).unwrap();
}
assert!(node.is_leader());Sourcepub fn leader(&self) -> Option<NodeId>
pub fn leader(&self) -> Option<NodeId>
Returns the leader the node currently recognises, if any.
Sourcepub fn commit_index(&self) -> Index
pub fn commit_index(&self) -> Index
Returns the highest log index known to be committed.
Sourcepub fn last_applied(&self) -> Index
pub fn last_applied(&self) -> Index
Returns the highest log index the node has applied.
Sourcepub fn log(&self) -> &L
pub fn log(&self) -> &L
Returns a shared reference to the underlying log.
§Examples
use raft_io::{RaftConfig, RaftNode, RaftLog};
let node = RaftNode::new(RaftConfig::single(1));
assert_eq!(node.log().last_index(), 0);Sourcepub fn members(&self) -> &[NodeId] ⓘ
pub fn members(&self) -> &[NodeId] ⓘ
Returns the current voting membership of the cluster.
This reflects the latest configuration the node has in its log, which it adopts as soon as the configuration entry is appended (before it commits).
§Examples
use raft_io::{RaftConfig, RaftNode};
let node = RaftNode::new(RaftConfig::new(1, [2, 3]));
assert_eq!(node.members(), &[1, 2, 3]);Sourcepub fn step(&mut self, event: Event) -> Result<Vec<Action>>
pub fn step(&mut self, event: Event) -> Result<Vec<Action>>
Advances the state machine by one Event and returns the resulting
Actions.
This is the only way to drive a node. Feed it ticks to let time pass, inbound messages as they arrive, and client proposals; act on every returned action, in order. The call is deterministic: the same node state and the same event always produce the same actions.
§Errors
Error::NotLeaderif the event isEvent::Proposeand this node is not the leader; the error carries the known leader so the caller can redirect.Error::Storageif the underlyingRaftLogfails on the durability path. A storage failure here is fatal to the node.
§Examples
use raft_io::{Action, Event, RaftConfig, RaftNode};
let mut node = RaftNode::new(RaftConfig::single(1));
while !node.is_leader() {
let _ = node.step(Event::Tick).unwrap();
}
let actions = node.step(Event::Propose(b"set x 1".to_vec())).unwrap();
assert!(actions.iter().any(|a| matches!(a, Action::Apply { .. })));