///|
/// Arguments for the RequestVote RPC (Raft §5.2), sent by a candidate to
/// gather votes for the term it is standing in.
pub(all) struct RequestVoteArgs {
term : UInt64
candidate_id : String
last_log_index : UInt64
last_log_term : UInt64
} derive(Eq)
///|
/// Reply to a RequestVote RPC. `term` lets a stale candidate discover it has
/// been superseded; `vote_granted` is true when the vote was given.
pub(all) struct RequestVoteReply {
term : UInt64
vote_granted : Bool
} derive(Eq)
///|
/// Arguments for the Heartbeat RPC (Raft §5.2): a leader's periodic liveness
/// beat. It carries no entries — only the leader's `commit` index (capped at
/// what the follower is known to hold) so a follower can advance its commit
/// index between AppendEntries. Modelling it as a distinct message (rather than
/// an empty AppendEntries) lets the leader treat a heartbeat acknowledgement as
/// pure liveness, separate from log-matching.
pub(all) struct HeartbeatArgs {
term : UInt64
leader_id : String
commit : UInt64
// An opaque read-index context echoed back by the follower, used by the
// ReadOnlySafe path to confirm leadership with a fresh quorum round-trip
// (Raft §6.4). Empty for an ordinary liveness beat.
context : Bytes
} derive(Eq)
///|
/// Reply to a Heartbeat RPC: the follower's term and the read-index context it
/// is acknowledging (echoed verbatim).
pub(all) struct HeartbeatReply {
term : UInt64
context : Bytes
} derive(Eq)
///|
/// Arguments for the AppendEntries RPC (Raft §5.3), used by the leader both
/// to replicate log entries and, with an empty `entries`, as a heartbeat.
pub(all) struct AppendEntriesArgs {
term : UInt64
leader_id : String
prev_log_index : UInt64
prev_log_term : UInt64
entries : Array[Entry]
leader_commit : UInt64
} derive(Eq)
///|
/// Reply to an AppendEntries RPC. `success` is true when the follower's log
/// contained a matching entry at `prev_log_index` and the entries were stored.
/// On success `match_index` is the highest index the follower now agrees on, so
/// the leader can advance its progress without guessing. On rejection
/// `conflict_index` is a hint at where the two logs diverge, letting the leader
/// back off in one jump instead of decrementing nextIndex one entry at a time
/// (the optimization sketched in Raft §5.3).
pub(all) struct AppendEntriesReply {
term : UInt64
success : Bool
match_index : UInt64
conflict_index : UInt64
// The term at `conflict_index` (0 if unknown), so the leader can run the same
// findConflictByTerm jump on its own log and skip a whole run of mismatched
// terms in one retry (Raft §5.3, two-sided).
conflict_term : UInt64
/// The probe point the follower rejected, echoing back the leader's
/// `prev_log_index`. This is etcd's `MsgAppResp.Index` on a rejection
/// (raft.go:1828, `Index: m.GetIndex()`): the leader feeds it as the
/// `rejected` argument to `MaybeDecrTo`, whose staleness guard compares it
/// against `next_index - 1` so a reordered reject for an entry no longer in
/// flight is discarded rather than driving a spurious back-off. On success it
/// is 0 and carries no meaning.
reject_index : UInt64
} derive(Eq)