Skip to content

Commit a8d92ad

Browse files
committed
Track reads on Raft leader
1 parent dac84b7 commit a8d92ad

File tree

6 files changed

+149
-44
lines changed

6 files changed

+149
-44
lines changed

src/raft/message.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,21 @@ pub enum Event {
4949
commit_index: Index,
5050
/// The term of the leader's last committed log entry.
5151
commit_term: Term,
52+
/// The latest read sequence number of the leader.
53+
read_seq: ReadSequence,
5254
},
5355
/// Followers confirm loyalty to leader after heartbeats.
5456
ConfirmLeader {
5557
/// The commit_index of the original leader heartbeat, to confirm
5658
/// read requests.
59+
///
60+
/// TODO: remove these when migrated to read_seq.
5761
commit_index: Index,
5862
/// If false, the follower does not have the entry at commit_index
5963
/// and would like the leader to replicate it.
6064
has_committed: bool,
65+
/// The read sequence number of the heartbeat we're responding to.
66+
read_seq: ReadSequence,
6167
},
6268

6369
/// Candidates solicit votes from all peers when campaigning for leadership.
@@ -113,6 +119,9 @@ pub enum Event {
113119
/// A client request ID.
114120
pub type RequestID = Vec<u8>;
115121

122+
/// A read sequence number, used to confirm leadership for linearizable reads.
123+
pub type ReadSequence = u64;
124+
116125
/// A client request.
117126
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
118127
pub enum Request {

src/raft/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod server;
55
mod state;
66

77
pub use self::log::{Entry, Index, Log};
8-
pub use message::{Address, Event, Message, Request, RequestID, Response};
8+
pub use message::{Address, Event, Message, ReadSequence, Request, RequestID, Response};
99
pub use node::{Node, NodeID, Status, Term};
1010
pub use server::Server;
1111
pub use state::{Driver, Instruction, State};

src/raft/node/candidate.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ mod tests {
210210
from: Address::Node(2),
211211
to: Address::Node(1),
212212
term: 3,
213-
event: Event::Heartbeat { commit_index: 2, commit_term: 1 },
213+
event: Event::Heartbeat { commit_index: 2, commit_term: 1, read_seq: 7 },
214214
})?;
215215
assert_node(&mut node).is_follower().term(3);
216216
assert_messages(
@@ -219,7 +219,7 @@ mod tests {
219219
from: Address::Node(1),
220220
to: Address::Node(2),
221221
term: 3,
222-
event: Event::ConfirmLeader { commit_index: 2, has_committed: true },
222+
event: Event::ConfirmLeader { commit_index: 2, has_committed: true, read_seq: 7 },
223223
}],
224224
);
225225
assert_messages(&mut state_rx, vec![]);
@@ -235,7 +235,7 @@ mod tests {
235235
from: Address::Node(2),
236236
to: Address::Node(1),
237237
term: 4,
238-
event: Event::Heartbeat { commit_index: 2, commit_term: 1 },
238+
event: Event::Heartbeat { commit_index: 2, commit_term: 1, read_seq: 7 },
239239
})?;
240240
assert_node(&mut node).is_follower().term(4);
241241
assert_messages(
@@ -244,7 +244,7 @@ mod tests {
244244
from: Address::Node(1),
245245
to: Address::Node(2),
246246
term: 4,
247-
event: Event::ConfirmLeader { commit_index: 2, has_committed: true },
247+
event: Event::ConfirmLeader { commit_index: 2, has_committed: true, read_seq: 7 },
248248
}],
249249
);
250250
assert_messages(&mut state_rx, vec![]);
@@ -259,7 +259,7 @@ mod tests {
259259
from: Address::Node(2),
260260
to: Address::Node(1),
261261
term: 2,
262-
event: Event::Heartbeat { commit_index: 1, commit_term: 1 },
262+
event: Event::Heartbeat { commit_index: 1, commit_term: 1, read_seq: 7 },
263263
})?;
264264
assert_node(&mut node).is_candidate().term(3);
265265
assert_messages(&mut node_rx, vec![]);
@@ -299,7 +299,7 @@ mod tests {
299299
from: Address::Node(1),
300300
to: Address::Broadcast,
301301
term: 3,
302-
event: Event::Heartbeat { commit_index: 2, commit_term: 1 },
302+
event: Event::Heartbeat { commit_index: 2, commit_term: 1, read_seq: 0 },
303303
},
304304
);
305305

src/raft/node/follower.rs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ impl RawNode<Follower> {
142142
// The leader will send periodic heartbeats. If we don't have a
143143
// leader in this term yet, follow it. If the commit_index advances,
144144
// apply state transitions.
145-
Event::Heartbeat { commit_index, commit_term } => {
145+
Event::Heartbeat { commit_index, commit_term, read_seq } => {
146146
// Check that the heartbeat is from our leader.
147147
let from = msg.from.unwrap();
148148
match self.role.leader {
@@ -160,7 +160,10 @@ impl RawNode<Follower> {
160160
self.state_tx.send(Instruction::Apply { entry })?;
161161
}
162162
}
163-
self.send(msg.from, Event::ConfirmLeader { commit_index, has_committed })?;
163+
self.send(
164+
msg.from,
165+
Event::ConfirmLeader { commit_index, has_committed, read_seq },
166+
)?;
164167
}
165168

166169
// Replicate entries from the leader. If we don't have a leader in
@@ -329,7 +332,7 @@ pub mod tests {
329332
from: Address::Node(2),
330333
to: Address::Node(1),
331334
term: 3,
332-
event: Event::Heartbeat { commit_index: 3, commit_term: 2 },
335+
event: Event::Heartbeat { commit_index: 3, commit_term: 2, read_seq: 7 },
333336
})?;
334337
assert_node(&mut node).is_follower().term(3).leader(Some(2)).voted_for(None).committed(3);
335338
assert_messages(
@@ -338,7 +341,7 @@ pub mod tests {
338341
from: Address::Node(1),
339342
to: Address::Node(2),
340343
term: 3,
341-
event: Event::ConfirmLeader { commit_index: 3, has_committed: true },
344+
event: Event::ConfirmLeader { commit_index: 3, has_committed: true, read_seq: 7 },
342345
}],
343346
);
344347
assert_messages(
@@ -358,7 +361,7 @@ pub mod tests {
358361
from: Address::Node(2),
359362
to: Address::Node(1),
360363
term: 3,
361-
event: Event::Heartbeat { commit_index: 3, commit_term: 3 },
364+
event: Event::Heartbeat { commit_index: 3, commit_term: 3, read_seq: 7 },
362365
})?;
363366
assert_node(&mut node).is_follower().term(3).leader(Some(2)).voted_for(None).committed(2);
364367
assert_messages(
@@ -367,7 +370,7 @@ pub mod tests {
367370
from: Address::Node(1),
368371
to: Address::Node(2),
369372
term: 3,
370-
event: Event::ConfirmLeader { commit_index: 3, has_committed: false },
373+
event: Event::ConfirmLeader { commit_index: 3, has_committed: false, read_seq: 7 },
371374
}],
372375
);
373376
assert_messages(&mut state_rx, vec![]);
@@ -382,7 +385,7 @@ pub mod tests {
382385
from: Address::Node(2),
383386
to: Address::Node(1),
384387
term: 3,
385-
event: Event::Heartbeat { commit_index: 5, commit_term: 3 },
388+
event: Event::Heartbeat { commit_index: 5, commit_term: 3, read_seq: 7 },
386389
})?;
387390
assert_node(&mut node).is_follower().term(3).leader(Some(2)).voted_for(None).committed(2);
388391
assert_messages(
@@ -391,7 +394,7 @@ pub mod tests {
391394
from: Address::Node(1),
392395
to: Address::Node(2),
393396
term: 3,
394-
event: Event::ConfirmLeader { commit_index: 5, has_committed: false },
397+
event: Event::ConfirmLeader { commit_index: 5, has_committed: false, read_seq: 7 },
395398
}],
396399
);
397400
assert_messages(&mut state_rx, vec![]);
@@ -408,7 +411,7 @@ pub mod tests {
408411
from: Address::Node(3),
409412
to: Address::Node(1),
410413
term: 3,
411-
event: Event::Heartbeat { commit_index: 5, commit_term: 3 },
414+
event: Event::Heartbeat { commit_index: 5, commit_term: 3, read_seq: 7 },
412415
})
413416
.unwrap();
414417
}
@@ -422,7 +425,7 @@ pub mod tests {
422425
from: Address::Node(3),
423426
to: Address::Node(1),
424427
term: 3,
425-
event: Event::Heartbeat { commit_index: 3, commit_term: 2 },
428+
event: Event::Heartbeat { commit_index: 3, commit_term: 2, read_seq: 7 },
426429
})?;
427430
assert_node(&mut node).is_follower().term(3).leader(Some(3)).voted_for(None).committed(3);
428431
assert_messages(
@@ -431,7 +434,7 @@ pub mod tests {
431434
from: Address::Node(1),
432435
to: Address::Node(3),
433436
term: 3,
434-
event: Event::ConfirmLeader { commit_index: 3, has_committed: true },
437+
event: Event::ConfirmLeader { commit_index: 3, has_committed: true, read_seq: 7 },
435438
}],
436439
);
437440
assert_messages(
@@ -451,7 +454,7 @@ pub mod tests {
451454
from: Address::Node(2),
452455
to: Address::Node(1),
453456
term: 3,
454-
event: Event::Heartbeat { commit_index: 1, commit_term: 1 },
457+
event: Event::Heartbeat { commit_index: 1, commit_term: 1, read_seq: 7 },
455458
})?;
456459
assert_node(&mut node).is_follower().term(3).leader(Some(2)).voted_for(None).committed(2);
457460
assert_messages(
@@ -460,7 +463,7 @@ pub mod tests {
460463
from: Address::Node(1),
461464
to: Address::Node(2),
462465
term: 3,
463-
event: Event::ConfirmLeader { commit_index: 1, has_committed: true },
466+
event: Event::ConfirmLeader { commit_index: 1, has_committed: true, read_seq: 7 },
464467
}],
465468
);
466469
assert_messages(&mut state_rx, vec![]);
@@ -475,7 +478,7 @@ pub mod tests {
475478
from: Address::Node(3),
476479
to: Address::Node(1),
477480
term: 4,
478-
event: Event::Heartbeat { commit_index: 3, commit_term: 2 },
481+
event: Event::Heartbeat { commit_index: 3, commit_term: 2, read_seq: 7 },
479482
})?;
480483
assert_node(&mut node).is_follower().term(4).leader(Some(3)).voted_for(None);
481484
assert_messages(
@@ -484,7 +487,7 @@ pub mod tests {
484487
from: Address::Node(1),
485488
to: Address::Node(3),
486489
term: 4,
487-
event: Event::ConfirmLeader { commit_index: 3, has_committed: true },
490+
event: Event::ConfirmLeader { commit_index: 3, has_committed: true, read_seq: 7 },
488491
}],
489492
);
490493
assert_messages(
@@ -504,7 +507,7 @@ pub mod tests {
504507
from: Address::Node(2),
505508
to: Address::Node(1),
506509
term: 2,
507-
event: Event::Heartbeat { commit_index: 3, commit_term: 2 },
510+
event: Event::Heartbeat { commit_index: 3, commit_term: 2, read_seq: 7 },
508511
})?;
509512
assert_node(&mut node).is_follower().term(3).leader(Some(2)).voted_for(None).committed(2);
510513
assert_messages(&mut node_rx, vec![]);
@@ -989,7 +992,7 @@ pub mod tests {
989992
from: Address::Node(3),
990993
to: Address::Node(1),
991994
term: 4,
992-
event: Event::Heartbeat { commit_index: 3, commit_term: 2 },
995+
event: Event::Heartbeat { commit_index: 3, commit_term: 2, read_seq: 7 },
993996
})?;
994997
assert_node(&mut node).is_follower().term(4).leader(Some(3)).forwarded(vec![]);
995998
assert_messages(
@@ -1005,7 +1008,11 @@ pub mod tests {
10051008
from: Address::Node(1),
10061009
to: Address::Node(3),
10071010
term: 4,
1008-
event: Event::ConfirmLeader { commit_index: 3, has_committed: true },
1011+
event: Event::ConfirmLeader {
1012+
commit_index: 3,
1013+
has_committed: true,
1014+
read_seq: 7,
1015+
},
10091016
},
10101017
],
10111018
);
@@ -1033,15 +1040,19 @@ pub mod tests {
10331040
from: Address::Node(2),
10341041
to: Address::Node(1),
10351042
term: 3,
1036-
event: Event::Heartbeat { commit_index: 2, commit_term: 1 },
1043+
event: Event::Heartbeat { commit_index: 2, commit_term: 1, read_seq: 7 },
10371044
})?;
10381045
assert_messages(
10391046
&mut node_rx,
10401047
vec![Message {
10411048
from: Address::Node(1),
10421049
to: Address::Node(2),
10431050
term: 3,
1044-
event: Event::ConfirmLeader { commit_index: 2, has_committed: true },
1051+
event: Event::ConfirmLeader {
1052+
commit_index: 2,
1053+
has_committed: true,
1054+
read_seq: 7,
1055+
},
10451056
}],
10461057
)
10471058
}

0 commit comments

Comments
 (0)