Skip to content

fix: avoid 500s on component pages from cached empty readme - #730

Open
vvtimofeev wants to merge 1 commit into
mainfrom
fix/issue-729-component-500
Open

fix: avoid 500s on component pages from cached empty readme#730
vvtimofeev wants to merge 1 commit into
mainfrom
fix/issue-729-component-500

Conversation

@vvtimofeev

Copy link
Copy Markdown
Contributor

What

Fixes the intermittent 500s on /components/<libId>/<componentId> pages reported in #729.

Root cause. Component readmes were fetched from raw.githubusercontent.com without authentication. Those requests share a per-IP rate limit, and when one failed, fetchComponentReadme swallowed the error and returned ''. CacheQuery then cached that empty string as fresh content for the whole 1-hour TTL, while fetchComponentReadmeWithCache throws on empty content — so a single failed fetch poisoned the instance and made the page return 500 for up to an hour. With several instances behind the balancer, the same URL flapped between 200 and 500 depending on which pod served it.

Changes

  • Fetch readme / changelog / CODEOWNERS through the authenticated Octokit client (new fetchGithubRawFile helper) instead of unauthenticated raw.githubusercontent.com requests, with one retry. 404 returns null so locale fallback keeps working; other errors are thrown after the retry.
  • Throw on empty component readme instead of returning '', so a transient failure leaves the cache in the error state and is retried on the next request instead of being cached as valid empty content.
  • Wait for readme cache revalidation (immediateResponse: false) — a request hitting a stale/errored entry gets fresh content instead of an instant null → 500; stale-but-present data is still served if the refetch fails.
  • CacheQuery.getData: awaiting the in-flight query promise no longer lets its rejection escape past the onError handler.
  • Respond 404 instead of 500 for components without a readme urlisComingSoon components (e.g. /components/navigation/action-bar) previously hit an unhandled throw and consistently returned 500 in production.

Note on rate limits

This moves readme traffic from the per-IP raw limit onto the GitHub App / token API quota. Worst-case estimate is ~750 req/hour per instance (readme cache misses dominate: locales without local docs fall back to the English readme per locale). Two cheap follow-ups can cut this by an order of magnitude if needed: dedupe fallback fetches per file rather than per locale, and raise the readme cache TTL — component readmes are fetched by version tag, so their content is immutable until a redeploy.

Testing

  • npm run typecheck, ESLint and Prettier clean (warnings at pre-existing baseline)
  • Verified on a local dev server: en/ru component pages render readmes via the API path (__NEXT_DATA__ contains localized content), missing README-ru falls back to English with a 200 (/ru/components/date-components/calendar), /components/navigation/action-bar now returns 404 instead of 500, smoke-checked /, /libraries, /libraries/uikit in en/ru

Fixes #729

🤖 Generated with Claude Code

- Fetch readme/changelog/CODEOWNERS through the authenticated Octokit
  client instead of unauthenticated raw.githubusercontent.com requests,
  which share a per-IP rate limit and intermittently returned errors in
  production (with one retry; 404 still falls back to the default locale)
- Throw on empty component readme instead of returning '', so a transient
  fetch failure is retried on the next request instead of being cached as
  valid empty content for the whole TTL
- Wait for readme cache revalidation instead of immediately returning a
  possibly empty cache entry
- Don't let a rejected in-flight query escape CacheQuery.getData past the
  onError handler
- Respond 404 instead of 500 for components without a readme url (e.g.
  isComingSoon ones like /components/navigation/action-bar)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

500 in components

2 participants