aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm')
-rw-r--r--src/swarm/members.rs12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/swarm/members.rs b/src/swarm/members.rs
index 59c7571..05c6501 100644
--- a/src/swarm/members.rs
+++ b/src/swarm/members.rs
@@ -216,12 +216,15 @@ pub(crate) fn alive_at(doc: &impl ReadDoc, pk: &str) -> Option<u64> {
}
/// The members that said they are alive within `window` before `now_ms` (sorted): the
-/// electorate of a remake (`remake::coordinator`).
+/// electorate of a remake (`remake::coordinator`). A stamp further in the future than a
+/// renewal interval (`alive_renewal`) doesn't count: its node's clock is that far ahead
+/// (it warns about it, `swarm::skew`), and the stamp would never age out.
pub(crate) fn electorate(doc: &impl ReadDoc, now_ms: u64, window: Duration) -> Vec<String> {
let oldest = now_ms.saturating_sub(window.as_millis() as u64);
+ let newest = now_ms.saturating_add(alive_renewal(window).as_millis() as u64);
members(doc)
.into_iter()
- .filter(|pk| alive_at(doc, pk).is_some_and(|at| at >= oldest))
+ .filter(|pk| alive_at(doc, pk).is_some_and(|at| (oldest..=newest).contains(&at)))
.collect()
}
@@ -389,6 +392,9 @@ mod tests {
("stale", json!({ "since": 1, "alive": now - 8 * day })),
("new", json!({ "since": now - day })),
("old", json!({ "since": 1 })),
+ // A clock a day ahead is tolerated (one renewal interval); a week isn't.
+ ("ahead", json!({ "since": 1, "alive": now + day })),
+ ("future", json!({ "since": 1, "alive": now + 7 * day })),
];
change(&mut doc, |doc| {
for (pk, entry) in entries {
@@ -397,7 +403,7 @@ mod tests {
});
assert_eq!(
electorate(&doc, now, Duration::from_secs(7 * 24 * 3600)),
- ["fresh", "new"]
+ ["ahead", "fresh", "new"]
);
}