diff --git a/neode-ui/src/views/Cloud.vue b/neode-ui/src/views/Cloud.vue index ca3eb88c..5eace497 100644 --- a/neode-ui/src/views/Cloud.vue +++ b/neode-ui/src/views/Cloud.vue @@ -963,9 +963,31 @@ function loadCounts() { // own comment and by CloudPeersRefresh.test.ts, which mounts this view bare) // — Vue only fires it automatically on first mount for a component that // already has a KeepAlive ancestor. onMounted guarantees this still runs -// once for a bare mount; the harmless extra pass onActivated makes on a -// KeepAlive-wrapped first mount is absorbed by the staleness/inflight guards -// above. +// once for a bare mount. +// +// 02-08 fix (real-hardware regression, not merely a "harmless extra pass"): +// individually each of loadCounts/loadPeers/loadPeerFiles is staleness- or +// inflight-deduped, so the ORIGINAL 02-04 assumption that firing this twice +// back-to-back is free held up per-resource. But the two back-to-back calls +// still fire loadPeerFiles's full content.browse-peer fan-out (one RPC per +// connected peer) essentially twice in the same tick before either pass's +// results land, and layered on top of whatever other KeepAlive-cached view +// happened to be mounting/activating at the same moment (Home/Server's own +// onMounted bursts), this measurably doubles the concurrent same-origin +// request volume at the single riskiest instant in the session — first +// activation. On archi-dev-box that volume was large enough to leave one +// in-flight File Browser request permanently stuck (never resolving, +// confirmed via direct reproduction), which then starved the browser's +// per-origin connection pool and silently broke every subsequent +// same-origin fetch for the rest of the session, including the lazy route +// chunks any later tab/folder navigation needs — "no folders open on +// click" was a downstream symptom of that stall, not a router or click- +// handler bug. A fresh-mount guard (the same pattern already used in +// Home.vue/Web5.vue/Mesh.vue/Server.vue) removes the redundant duplicate +// pass on first activation without changing steady-state reactivation +// behavior at all: onActivated still re-syncs normally on every later +// KeepAlive round-trip, exactly as before. +let cloudFreshMount = true async function syncOnEntry() { loadCounts() await loadPeers() @@ -975,7 +997,10 @@ async function syncOnEntry() { void loadPeerFiles() } onMounted(() => { void syncOnEntry() }) -onActivated(() => { void syncOnEntry() }) +onActivated(() => { + if (cloudFreshMount) { cloudFreshMount = false; return } + void syncOnEntry() +}) // File Browser can finish its startup scan after we mount — pick counts up // the moment it becomes available instead of showing a permanent blank.