feat(02-05): cache the six Mesh tab-entry fetch groups without serializing them

- Mesh.vue: six useCachedResource entries wrap mesh.refreshAll(),
  transport.fetchStatus(), refreshFederationNodes(), refreshSelfOnion(),
  refreshSelfDid() and refreshContacts(), each with an explicit TTL
  (10s reachability/transport, 30s federation/contacts, 300s self
  DID/onion) and persist decision (T-02-01: every group carrying peer
  or self identity data is persist:false; only aggregate transport
  status may persist)
- armMeshLive's Promise.all fan-out becomes a single Promise.allSettled
  over refreshMeshGroupIfStale() per group, so a revisit inside TTL
  issues zero RPC, a stale revisit revalidates concurrently (not a
  serial chain, T-02-16), and one rejected group never blocks the rest
- RefreshIndicator wired into the Mesh header, driven by whether any of
  the six groups is refreshing — visible while peer reachability
  revalidates on re-entry so a resumed tab never shows a frozen
  reachability state as current (T-02-13)
- dedup: true added to every underlying rpc-client.ts/mesh.ts/
  transport.ts fetcher call backing the six groups
- useCachedResource() calls live in Mesh.vue rather than inside
  stores/mesh.ts or stores/transport.ts: Pinia's defineStore(id, setup)
  runs in a bare effectScope, not a component instance, so the
  composable's internal onActivated() would silently no-op there; the
  fetchers still wrap the stores' own actions unchanged, so those
  actions' other callers (clearAllMesh, setMeshOnly, the pre-send
  balance check) keep their guaranteed-fresh, uncached reads

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-07-30 16:14:32 -04:00
co-authored by Claude Fable 5
parent e582124259
commit 31389bcc3c
6 changed files with 507 additions and 9 deletions
+4 -1
View File
@@ -350,6 +350,7 @@ class RPCClient {
return this.call({
method: 'node.did',
params: {},
dedup: true, // read-only identity lookup; safe to collapse concurrent callers (PERF-02)
})
}
@@ -577,6 +578,7 @@ class RPCClient {
return this.call({
method: 'node.tor-address',
params: {},
dedup: true, // read-only; near-static value, safe to collapse concurrent callers (PERF-02)
})
}
@@ -801,7 +803,7 @@ class RPCClient {
async meshContactsList(): Promise<{
contacts: Array<{ pubkey: string; alias?: string | null; notes?: string | null; pinned?: boolean; blocked?: boolean }>
}> {
return this.call({ method: 'mesh.contacts-list', params: {} })
return this.call({ method: 'mesh.contacts-list', params: {}, dedup: true }) // read-only (PERF-02)
}
async meshContactsSave(
@@ -842,6 +844,7 @@ class RPCClient {
return this.call({
method: 'federation.list-nodes',
params: {},
dedup: true, // read-only; safe to collapse concurrent callers (PERF-02)
})
}