Skip to main content

RaftNode

Struct RaftNode 

Source
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>

Source

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>

Source

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);
Source

pub fn id(&self) -> NodeId

Returns this node’s id.

Source

pub fn role(&self) -> Role

Returns the role the node currently plays.

Source

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());
Source

pub fn term(&self) -> Term

Returns the node’s current term.

Source

pub fn leader(&self) -> Option<NodeId>

Returns the leader the node currently recognises, if any.

Source

pub fn commit_index(&self) -> Index

Returns the highest log index known to be committed.

Source

pub fn last_applied(&self) -> Index

Returns the highest log index the node has applied.

Source

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);
Source

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]);
Source

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::NotLeader if the event is Event::Propose and this node is not the leader; the error carries the known leader so the caller can redirect.
  • Error::Storage if the underlying RaftLog fails 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 { .. })));

Auto Trait Implementations§

§

impl<L> Freeze for RaftNode<L>
where L: Freeze,

§

impl<L> RefUnwindSafe for RaftNode<L>
where L: RefUnwindSafe,

§

impl<L> Send for RaftNode<L>
where L: Send,

§

impl<L> Sync for RaftNode<L>
where L: Sync,

§

impl<L> Unpin for RaftNode<L>
where L: Unpin,

§

impl<L> UnsafeUnpin for RaftNode<L>
where L: UnsafeUnpin,

§

impl<L> UnwindSafe for RaftNode<L>
where L: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<E> WithErrorCode<E> for E

Source§

fn with_code(self, code: impl Into<String>) -> CodedError<E>

Attach an error code to an error