diff options
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 25 | ||||
| -rw-r--r-- | src/api/dashboard/mod.rs | 11 |
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( |
