krabka_kraft_core/action.rs
1//! Outputs from the consensus state machine. They are pure side-effect
2//! descriptions that the engine executes.
3
4use crate::types::{Epoch, LogOffsetMetadata, NodeId, SimInstant};
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub enum TimerKind {
8 Election,
9 Fetch,
10 /// Leader-side check-quorum watchdog (KAFKA-15489). It expires when a
11 /// majority of the voters has not fetched, and the leader then resigns.
12 CheckQuorum,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
16pub enum Action {
17 /// Broadcast a Vote request to all other voters, as a pre-vote or a real vote.
18 SendVoteRequest { epoch: Epoch, pre_vote: bool },
19 /// Reply to a Vote request.
20 ///
21 /// Kafka's `VoteResponse` carries no pre-vote flag. The candidate matches
22 /// the reply to its round by its own role, so the responder does not echo
23 /// `pre_vote`.
24 ReplyVote {
25 to: NodeId,
26 epoch: Epoch,
27 granted: bool,
28 },
29 /// New leader announces its epoch to all voters.
30 SendBeginQuorumEpoch { epoch: Epoch },
31 /// Resigning leader tells voters to elect.
32 SendEndQuorumEpoch {
33 epoch: Epoch,
34 /// The other voters, most caught up first by the fetch progress the
35 /// leader validated: Kafka's
36 /// `LeaderState.nonLeaderVotersByDescendingFetchOffset`.
37 preferred_successors: Vec<NodeId>,
38 },
39 /// The follower or observer should fetch from this leader.
40 SendFetch { leader_id: NodeId },
41 /// We changed role. The variant carries the new role name for
42 /// observability and for tests.
43 TransitionedTo(&'static str),
44 /// Persist the durable quorum state: epoch, votedKey, or leaderId changed.
45 PersistQuorumState,
46 /// As new leader, append the `LeaderChange` control record for `epoch`.
47 AppendLeaderChange { epoch: Epoch },
48 /// Leader advanced the high watermark.
49 AdvanceHighWatermark(i64),
50 /// Truncate this node's own log to this point. A follower emits it when
51 /// the leader answered its Fetch with a diverging epoch.
52 TruncateTo(LogOffsetMetadata),
53 /// Leader answers the Fetch it is serving with this diverging epoch. It is
54 /// a reply for the follower, and it changes nothing in the leader's own
55 /// log: the leader holds the records the follower must truncate to.
56 ReplyDivergingEpoch(LogOffsetMetadata),
57 /// Arm or re-arm a timer to fire at `deadline`.
58 ResetTimer {
59 kind: TimerKind,
60 deadline: SimInstant,
61 },
62}