perf(desktop): stop the Projects fan refetching on re-entry and running after leave (#6458)

Entering Projects fires a large fan: an exhaustive paginated relay
enumeration (projects/repos/tombstones), five 2,000-event work-item
queries plus assignment-operation scans, per-repo activity summaries,
and a local-repository filesystem scan. Measured on a large community
(101 issues / 258 PRs):

| query | measured cost |
|---|---|
| work-items (5 × 2,000-event REQs + assignment scans) | 3.5–3.9s |
| activity summaries | 4.1s |
| repository activity | 1.0–2.2s |
| local repository scan | 1.7s |

Two lifecycle bugs made the fan far more expensive than it needs to be:

- **Freshness windows guaranteed a full refetch on nearly every
re-entry** (60s enumeration, 30s work-items/activity, 10s local scan) —
i.e., the costs above were re-paid on almost every visit. Every local
write path already invalidates its keys explicitly (issue/PR mutations,
project creation, repo sync), so the short windows only served
remote-actor freshness. Raised to 5m/2m/2m with a 30m enumeration cache:
re-entries now paint from cache, and the fan re-runs at most every 2–5
minutes.
- **Leaving Projects left the whole fan running**, competing with the
next surface's channel fetches on the same relay connection. AbortSignal
is now threaded through the enumeration and assignment pagination loops
(optional params — behavior identical without a signal), and leaving the
surface cancels the work-items query. Deliberately NOT cancelled: the
enumeration (the always-mounted sidebar projects section observes it and
its 30m cache is valuable), repo snapshots and local scans (native work
that can't abort — cancelling would discard the finished result and
force the same clones again), and activity summaries (a single bounded
request).

Abort behavior is covered by red-first unit tests on both pagination
loops. Remaining follow-up (out of scope): the queries themselves want a
relay-side aggregate instead of shipping thousands of events to compute
counts client-side.

---------

Signed-off-by: Max Lampert <maxwell@squareup.com>
This commit is contained in:
Max Lampert
2026-08-21 16:40:35 -07:00
committed by GitHub
parent b0466ac465
commit b85d680fb1
10 changed files with 172 additions and 13 deletions

View File

@@ -63,6 +63,9 @@ test("relay invalidation separates relay project queries from local repo work",
["project", "project-1", "pull-requests"],
["projects", "issues", ["project-1"]],
["projects", "activity-summaries", ["addr-1"]],
// Work items fan out over the relay and are fresh for two minutes;
// reconnect auto-heal must be able to repair a partial result.
["projects", "work-items", ["project-1"], ["addr-1"]],
]) {
assert.equal(isRelayDependentQueryKey(queryKey), true, queryKey.join("/"));
}

View File

@@ -39,6 +39,10 @@ const RELAY_PROJECT_QUERY_PARTS = new Set<string>([
"activity-summaries",
"issues",
"pull-requests",
// Fresh for two minutes (PROJECT_WORK_ITEMS_STALE_TIME_MS) and tolerant of
// partial fan-out failure — reconnect auto-heal is what repairs a partial
// result inside that window.
"work-items",
]);
const LOCAL_PROJECT_QUERY_PARTS = new Set<string>([