1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! # raft-io
//!
//! A from-scratch implementation of the [Raft consensus algorithm], built as a
//! clean, embeddable library rather than a framework.
//!
//! The protocol core is a **deterministic state machine**: you feed it
//! [`Event`]s (logical ticks, inbound [`Message`]s, client proposals) and it
//! returns [`Action`]s (send these messages, apply this committed command).
//! Time, networking, and storage are *your* concern, injected through the
//! [`RaftLog`] and [`RaftTransport`] trait seams. That separation is exactly
//! what makes the consensus core provable: it contains no wall clock and no
//! I/O, so an entire cluster's behaviour can be reproduced from a seed and a
//! sequence of events.
//!
//! ## Status
//!
//! This is `v0.8`: **alpha — feature complete, hardened, in consumer
//! integration.** The full protocol — election (with [pre-vote] disruption
//! protection), replication, durable crash recovery (`persistence`), snapshots,
//! membership changes, and leadership transfer — is in place and verified by a
//! kitchen-sink adversarial test suite that asserts all five Raft safety
//! properties under combined partitions, message loss/reorder/duplication,
//! membership churn, and snapshotting, plus an application-level suite that
//! drives a replicated key-value store to convergence under the same faults. The
//! public traits and the wire and WAL formats are frozen (see `docs/PROTOCOL.md`);
//! the decode path is fuzzed. Additions in this line stay MINOR-compatible — the
//! pre-vote messages, for instance, are new `#[non_exhaustive]` enum variants that
//! leave every existing wire and WAL encoding untouched. See `docs/API.md` for the
//! full surface.
//!
//! [pre-vote]: PreVote
//!
//! ## The three tiers
//!
//! - **Tier 1** — the common case in a handful of calls, no builder and no
//! generic to name: [`RaftNode::new`] with a [`RaftConfig`] and the default
//! in-memory [`MemoryLog`].
//! - **Tier 2** — [`RaftConfig`]'s builder for tuning election and heartbeat
//! timing.
//! - **Tier 3** — the [`RaftLog`] / [`RaftTransport`] traits for plugging in a
//! durable store or a real transport.
//!
//! ## Example — a single-node cluster elects itself and commits
//!
//! ```
//! use raft_io::{Action, Event, RaftConfig, RaftNode};
//!
//! // One node, no peers: it reaches quorum (itself) the moment it times out.
//! let mut node = RaftNode::new(RaftConfig::single(1));
//!
//! // Drive logical ticks until the node becomes leader.
//! while !node.is_leader() {
//! let _ = node.step(Event::Tick).expect("tick never fails in memory");
//! }
//! assert_eq!(node.leader(), Some(1));
//!
//! // A leader commits its own proposals immediately (quorum of one).
//! let actions = node.step(Event::Propose(b"set x = 1".to_vec())).unwrap();
//! assert!(actions.iter().any(|a| matches!(a, Action::Apply { .. })));
//! assert_eq!(node.commit_index(), 1);
//! ```
//!
//! [Raft consensus algorithm]: https://raft.github.io/
pub use crateRaftConfig;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crateWalLog;
/// The everyday surface, for `use raft_io::prelude::*;`.
///
/// This gathers the types an application touches while driving a node — the node
/// and its config, the [`Event`]/[`Action`] vocabulary, the error type, and the
/// log and transport seams with their in-memory implementations. The message and
/// other value types are available from the crate root when needed (for example
/// when implementing a transport or inspecting a [`LogEntry`]).
///
/// # Examples
///
/// ```
/// use raft_io::prelude::*;
///
/// let mut node = RaftNode::new(RaftConfig::single(1));
/// while !node.is_leader() {
/// let _ = node.step(Event::Tick).unwrap();
/// }
/// assert!(node.is_leader());
/// ```