aboutsummaryrefslogtreecommitdiffstats
path: root/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/api')
-rw-r--r--src/api/dashboard/dashboard.html25
-rw-r--r--src/api/dashboard/mod.rs11
2 files changed, 25 insertions, 11 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html
index 1bd2a19..1f27544 100644
--- a/src/api/dashboard/dashboard.html
+++ b/src/api/dashboard/dashboard.html
@@ -2017,21 +2017,28 @@ function openDashboard(id) {
requestAnimationFrame(step);
}
// Nodes that entered a new epoch (a remake: `remakes.md`) shine: a golden halo grows
-// from the node and fades, as a breath, larger. Known for this node and its peers
-// (`/peers`: `localEpoch`, each peer's `epoch`); others' epochs the page doesn't see.
-const SHINE_MS = 1600;
+// from the node and fades, as a breath, larger. Their epochs come from `/peers` (this
+// node's, `localEpoch`, and each peer's) and from the links members report
+// (`graph.measured`, each with the epoch its member said it is in), so for every member
+// that reports. Only a later generation than the page knew shines, and only from a
+// report of the last two minutes: a late or older report doesn't make it shine again.
+const SHINE_MS = 1600, SHINE_FRESH_SECS = 120;
const knownEpochs = new Map();
function epochsArrived() {
if (!state) return;
- const current = new Map();
- if (state.peers.localEpoch) current.set(state.node.id, state.peers.localEpoch.id);
+ const seen = [];
+ if (state.peers.localEpoch) seen.push([state.node.id, state.peers.localEpoch, 0]);
for (const [id, peer] of Object.entries(state.peers.peers)) {
- if (peer.epoch) current.set(id, peer.epoch.id);
+ if (peer.epoch) seen.push([id, peer.epoch, 0]);
+ }
+ for (const [id, report] of Object.entries(state.graph.measured)) {
+ if (report.epoch) seen.push([id, report.epoch, report.secsAgo || 0]);
}
- for (const [id, epoch] of current) {
+ for (const [id, epoch, secsAgo] of seen) {
const was = knownEpochs.get(id);
- if (was !== undefined && was !== epoch) shine(id);
- knownEpochs.set(id, epoch);
+ if (was !== undefined && epoch.generation <= was) continue;
+ if (was !== undefined && secsAgo <= SHINE_FRESH_SECS) shine(id);
+ knownEpochs.set(id, epoch.generation);
}
}
function shine(id) {
diff --git a/src/api/dashboard/mod.rs b/src/api/dashboard/mod.rs
index 6682cbd..c82ce76 100644
--- a/src/api/dashboard/mod.rs
+++ b/src/api/dashboard/mod.rs
@@ -340,15 +340,22 @@ async fn build(state: &AppState, graph: &Graph, live: bool) -> JsonValue {
.into_iter()
.filter(|(_, age, _)| *age <= LINKS_KEPT_FOR)
.collect();
+ // With each its epoch: the page shows who entered a new one.
+ let epochs = state.links.epochs();
+ let epoch_json = |epoch: Option<crate::transport::Epoch>| {
+ epoch.map(|epoch| json!(crate::document::replica::EpochRecord::from(epoch)))
+ };
let mut measured = Map::new();
measured.insert(
local.to_owned(),
- json!({ "secsAgo": 0, "links": links_json(&own) }),
+ json!({ "secsAgo": 0, "links": links_json(&own),
+ "epoch": epoch_json(Some(state.local_epoch())) }),
);
for (member, age, member_links) in &replies {
measured.insert(
member.clone(),
- json!({ "secsAgo": age.as_secs(), "links": links_json(member_links) }),
+ json!({ "secsAgo": age.as_secs(), "links": links_json(member_links),
+ "epoch": epoch_json(epochs.get(member).copied()) }),
);
}
let clocks = clocks::swarm(