fix(contributor-card): retry failed fetches instead of hiding the card forever#38
Merged
Merged
Conversation
…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).
…failed-fetch-retry
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).
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.
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
fetchContributorInforeturnsnullon any error (rate limit, network blip, service-worker hiccup).sync()then cached that null:and the cache-hit branch renders nothing for a null entry and never refetches:
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
infoCache: Map<string, ContributorInfo>).failedFetchAtwith 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
pnpm test→ 227 passing.pnpm buildclean.