Skip to content

fix(contributor-card): retry failed fetches instead of hiding the card forever#38

Merged
rrbe merged 3 commits into
mainfrom
fix/contributor-card-failed-fetch-retry
Jun 24, 2026
Merged

fix(contributor-card): retry failed fetches instead of hiding the card forever#38
rrbe merged 3 commits into
mainfrom
fix/contributor-card-failed-fetch-retry

Conversation

@rrbe

@rrbe rrbe commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Symptom

The contributor card sometimes never appears for a user (no card, not even a loading skeleton) and stays gone until a full page reload. It looked page-specific — e.g. "works on the PR detail page, but not on the PR list" — but isn't.

Root cause

fetchContributorInfo returns null on any error (rate limit, network blip, service-worker hiccup). sync() then cached that null:

infoCache.set(cacheKey, data ?? null);

and the cache-hit branch renders nothing for a null entry and never refetches:

if (infoCache.has(cacheKey)) {
  existing?.remove();
  const info = infoCache.get(cacheKey);
  if (info) placePanel(card, buildPanel(login, info)); // null → nothing, forever
  return;
}

So a single transient failure permanently suppressed the card for that user for the rest of the session. The "PR list vs detail" pattern was just whichever hover happened to poison the cache first (the cache key is repo#login, page-independent).

Fix

  • Cache successful fetches only (infoCache: Map<string, ContributorInfo>).
  • Record failures in failedFetchAt with a timestamp and retry after a 60s cooldown (and on any fresh load — the maps are in-memory). The cooldown stops a busy hovercard from re-fetching on every DOM re-render, while still recovering on a later hover.
  • cleanupContributorCard() clears the new map too.

Verification

  • Live (Chrome, real hover on the PR list page): before the fix, CodyTseng's card stayed absent for 3s+ (no skeleton). After clearing the in-memory cache (page reload), the same hover fetched and rendered fine (skeleton → real card in ~1.6s) — confirming the fetch works and the poisoned null cache was the cause.
  • Added a regression test: a failed fetch shows nothing, does not refetch within the cooldown (no network storm), and retries after the cooldown — then renders the card.
  • pnpm test → 227 passing. pnpm build clean.

rrbe added 3 commits June 24, 2026 00:47
…d forever

fetchContributorInfo returns null on ANY error (rate limit, network blip,
service-worker hiccup). sync() cached that null in infoCache, and the
cache-hit branch renders nothing for a null entry and never refetches —
so a single transient failure hid the contributor card for that user for
the rest of the session (until a full page reload). This looked
page-specific (e.g. 'works on the PR detail page, not the PR list') but
was really just whichever hover happened to poison the cache first.

Now only successful fetches are cached. A failure is recorded in
failedFetchAt with a timestamp and retried after a 60s cooldown (and on
any fresh load, since the maps are in-memory). The cooldown keeps a busy
hovercard from re-fetching on every DOM re-render while still recovering
on a later hover. cleanupContributorCard clears the new map too.

Verified live: with the cache cleared, the card fetches and renders fine
on the PR list page — confirming the fetch itself works and the poisoned
null cache was the cause. Added a regression test (retry after cooldown,
no refetch storm within it).
A failed fetch removed the skeleton via a login-unscoped selector against
the captured container. If the user hovered past to another user before the
slow fetch resolved, the failure callback yanked the *new* user's in-flight
skeleton. Scope the removal by data-login so a since-passed fetch can't blank
the card now loading a different user.

Also collapse the now-identical null-return and thrown-error paths into one
onFailure helper, so the two failure branches can't drift.

Add a regression test asserting node identity (a later sync() re-adds a
different skeleton, masking the bug if you only assert presence).
@rrbe rrbe merged commit d33471c into main Jun 24, 2026
1 check passed
@rrbe rrbe deleted the fix/contributor-card-failed-fetch-retry branch June 24, 2026 01:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant