perf(extension): render stack surfaces from localStorage cache before network#479
Merged
Conversation
Contributor
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 Required ReviewsWonderful, this rule succeeded.
🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
🟢 🔎 ReviewsWonderful, this rule succeeded.
🟢 📕 PR descriptionWonderful, this rule succeeded.
|
There was a problem hiding this comment.
Pull request overview
Adds a localStorage-backed cache to render the Mergify stack context panel and floating stack navigation pill immediately on cold loads, then refreshes from the network and updates the cache.
Changes:
- Introduce
StackContextCache(localStorage, 1h TTL) to persist parsed stack + revision data by org/repo/PR. - Update
renderMergifyContextto render from cache synchronously before starting the network comment walk, then refresh and update/invalidate the cache.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/stacks.js |
Uses StackContextCache for cache-first rendering and cache update/invalidation during renderMergifyContext. |
src/cache.js |
Adds StackContextCache implementation backed by localStorage with TTL and remove/update helpers. |
Comments suppressed due to low confidence (2)
src/stacks.js:758
- Cache invalidation on
!panelis potentially too aggressive:parseStackMarkercan return null for transient reasons (e.g., it explicitly rejects markers that don't match the current PR when stale DOM IDs are fetched during SPA navigation). In that case, removing the localStorage entry discards the last-known-good cache and defeats the cache-first speedup on the next tick. Consider only removing the cache when you have a strong signal the stack is gone (e.g.,bodies.length === 0or none of the fetched bodies contain either marker prefix), and otherwise keep the cached entry while still removing surfaces for this tick.
const stackData = parseStackMarker(bodies, currentPull.number);
const revisionData = parseRevisionMarker(bodies, currentPull.number);
const panel = buildContextPanel(stackData, revisionData, currentPull);
if (!panel) {
_stackContextCache.remove(
currentPull.org,
currentPull.repo,
currentPull.number,
);
removeContextSurfaces(currentPull);
src/cache.js:132
get()treats entries with a missing/invalidtimestampas non-expiring becauseDate.now() - data.timestampbecomesNaNand the TTL check never triggers. It would be safer to validatetimestampis a finite number and treat anything else as expired (removing the key) to avoid sticky stale cache entries.
try {
const raw = localStorage.getItem(k);
if (!raw) return null;
const data = JSON.parse(raw);
if (Date.now() - data.timestamp > this.expirationMs) {
localStorage.removeItem(k);
return null;
}
return {
stackData: data.stackData ?? null,
revisionData: data.revisionData ?? null,
};
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… network
Mirror the merge-box queue-row speedup for the stack context panel and the
floating stack-nav pill. Previously both surfaces only appeared after
`renderMergifyContext` finished its full network walk:
1. Find Mergify comment IDs (DOM scan or fetch the ~500KB Conversation HTML
on the Files tab).
2. Fetch each comment body (4 parallel workers).
3. Parse stack + revision markers.
The in-memory caches (`_commentBodyCache`, `_remoteCommentIdsCache`) only
help within a single SPA session — they're lost on every hard reload, so
each cold load re-paid the full network walk before either surface drew
anything.
Add a localStorage-backed `StackContextCache` (1h TTL, keyed by
org/repo/PR) that stores the parsed `stackData` and `revisionData` —
both already plain JSON-serializable objects produced by
`parseStackMarker` / `parseRevisionMarker`. `renderMergifyContext` now:
- Reads the cache synchronously and, on hit, builds + injects the panel
and nav immediately. The surfaces are on screen before the comment
fetches even start.
- Continues the existing network refresh path. `injectContextPanel`
and `injectStackNav` already dedupe via `data-mergify-hash`, so when
the fresh data matches the cached render the second injection is a
no-op. When it differs, the surfaces are swapped in place.
- Invalidates the cache when the fresh fetch reports no Mergify
comments or no panel content, so a stale entry doesn't keep showing
after the stack is dismantled upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Change-Id: I02898eca47b9dfb1f7f19f8045120ba02d7eb64a
ff77f7c to
6fe7f18
Compare
Member
Author
Revision history
|
JulianMaurin
approved these changes
May 20, 2026
remyduthu
approved these changes
May 22, 2026
Contributor
Merge Queue Status
This pull request spent 2 minutes 18 seconds in the queue, including 1 minute 30 seconds running CI. Required conditions to merge
|
34 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Mirror the merge-box queue-row speedup for the stack context panel and the
floating stack-nav pill. Previously both surfaces only appeared after
renderMergifyContextfinished its full network walk:on the Files tab).
The in-memory caches (
_commentBodyCache,_remoteCommentIdsCache) onlyhelp within a single SPA session — they're lost on every hard reload, so
each cold load re-paid the full network walk before either surface drew
anything.
Add a localStorage-backed
StackContextCache(1h TTL, keyed byorg/repo/PR) that stores the parsed
stackDataandrevisionData—both already plain JSON-serializable objects produced by
parseStackMarker/parseRevisionMarker.renderMergifyContextnow:and nav immediately. The surfaces are on screen before the comment
fetches even start.
injectContextPaneland
injectStackNavalready dedupe viadata-mergify-hash, so whenthe fresh data matches the cached render the second injection is a
no-op. When it differs, the surfaces are swapped in place.
comments or no panel content, so a stale entry doesn't keep showing
after the stack is dismantled upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com