Skip to content

feat(cache): serve stale metrics on GitHub rate limits#2439

Merged
Priyanshu-byte-coder merged 1 commit into
Umbrella-io:mainfrom
bhavyajain0810:feat/github-rate-limit-cache-1930
Jun 16, 2026
Merged

feat(cache): serve stale metrics on GitHub rate limits#2439
Priyanshu-byte-coder merged 1 commit into
Umbrella-io:mainfrom
bhavyajain0810:feat/github-rate-limit-cache-1930

Conversation

@bhavyajain0810

Copy link
Copy Markdown
Contributor

Summary

Adds stale-cache fallback support for GitHub-backed metrics so previously successful data can still be returned when GitHub temporarily rate-limits a refresh. The pinned repositories endpoint now uses the shared cache and centralized GitHub GraphQL handling while preserving authentication and non-rate-limit error behavior.

Closes #1930


Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that changes existing behavior)
  • 📝 Documentation update
  • ♻️ Refactor / code cleanup (no functional change)
  • ⚡ Performance improvement
  • 🔒 Security fix
  • 🧪 Tests only

What Changed

  • Extended src/lib/metrics-cache.ts with an optional stale-cache layer, configurable stale-grace period, and error predicate for controlled fallback.
  • Updated src/app/api/metrics/pinned-repos/route.ts to use withMetricsCache, cache-bypass handling, and the centralized githubGraphQL helper.
  • Added fallback behavior that serves stale pinned-repository data only when a GitHub rate-limit error prevents fresh data from loading.
  • Updated cache deletion so both the fresh entry and its corresponding stale entry are removed.
  • Added tests in test/metrics-cache.test.ts for stale fallback, unrelated errors, explicit cache bypass, and deletion of stale entries.

How to Test

  1. Run the focused lint checks:

    npx eslint src/lib/metrics-cache.ts src/app/api/metrics/pinned-repos/route.ts test/metrics-cache.test.ts test/pinned-repos.test.ts
  2. Run the relevant tests:

    npm test -- test/metrics-cache.test.ts test/pinned-repos.test.ts
  3. Run TypeScript validation:

    npm run type-check

Expected result:

  • ESLint completes without errors.
  • Both relevant test files pass: 23 tests passed.
  • tsc --noEmit completes without TypeScript errors.
  • A normal cache hit avoids a GitHub request.
  • After the fresh entry expires, a recognized GitHub rate-limit error returns the stale value.
  • Unrelated errors are still propagated instead of being hidden by stale data.
  • Explicit cache-bypass requests do not use fresh or stale cache fallback.

Checklist

  • Linked the related issue above
  • Self-reviewed my own diff
  • No unnecessary console.log, debug code, or commented-out blocks
  • npm run lint passes locally
  • No TypeScript errors (npm run type-check)
  • Added or updated tests where applicable
  • Updated documentation / comments if behavior changed

Additional Context

  • This is an internal API and caching change with no UI impact, so screenshots and accessibility testing are not applicable.
  • Stale fallback is opt-in and only activates when the supplied error predicate approves the failure.
  • Cache-bypass requests continue to force a fresh request and do not silently fall back to stale data.
  • Existing authentication failures and unrelated GitHub API failures continue to return their normal error responses.

@github-actions github-actions Bot added gssoc26 GSSoC 2026 contribution type:feature GSSoC type bonus: new feature type:testing GSSoC type bonus: tests (+10 pts) labels Jun 14, 2026
@github-actions

Copy link
Copy Markdown

GSSoC Label Checklist 🏷️

@Umbrella-io — please apply the appropriate labels before merging:

Difficulty (pick one):

  • level:beginner — 20 pts
  • level:intermediate — 35 pts
  • level:advanced — 55 pts
  • level:critical — 80 pts

Quality (optional):

  • quality:clean — ×1.2 multiplier
  • quality:exceptional — ×1.5 multiplier

Validation (required to score):

  • gssoc:approved — counts for points
  • gssoc:invalid / gssoc:spam / gssoc:ai-slop — does not score

Type labels (type:*) are auto-detected from files and title. Review and adjust if needed.
Points formula: (difficulty × quality_multiplier) + type_bonus

@github-actions github-actions Bot added type:bug GSSoC type bonus: bug fix type:performance GSSoC type bonus: performance (+15 pts) labels Jun 14, 2026
@bhavyajain0810

Copy link
Copy Markdown
Contributor Author

Hi @Priyanshu-byte-coder,

CI status note

The two failing Playwright checks appear unrelated to the changes in this PR.

E2E smoke test

The failing test is:

e2e/streak.spec.ts
[Streak E2E] streak widget shows the mocked longest streak value

Playwright reports a strict-mode violation because:

[aria-label="Your longest streak ever"]

matches two existing elements: the longest-streak card and its information button. The same failure occurred across retries, while the other 46 smoke tests passed.

Visual regression

The visual-regression job failed in these existing UI scenarios:

landing page full page screenshot in dark mode
public profile screenshot with deterministic mock data

The public-profile test timed out while waiting for the expected profile heading. Neither these pages nor their visual tests are modified by this PR.

This PR only changes:

  • src/lib/metrics-cache.ts
  • src/app/api/metrics/pinned-repos/route.ts
  • test/metrics-cache.test.ts

All relevant validation is passing, including build, lint, type-check, test coverage, dependency audit, environment security checks, and the focused cache and pinned-repository tests.

Could you please review or rerun these unrelated Playwright failures?

@Priyanshu-byte-coder Priyanshu-byte-coder added the gssoc:approved GSSoC: PR approved for scoring label Jun 16, 2026
@Priyanshu-byte-coder Priyanshu-byte-coder merged commit 0679a02 into Umbrella-io:main Jun 16, 2026
12 of 14 checks passed
@github-actions

Copy link
Copy Markdown

🎉 Merged! Thanks for contributing to DevTrack.

If the project has been useful to you, a ⭐ star on the repo is the easiest way to support it — it helps DevTrack get discovered by more developers.

Keep an eye on open issues for your next contribution!

@Priyanshu-byte-coder Priyanshu-byte-coder added level:advanced GSSoC: Advanced difficulty (55 pts) quality:clean GSSoC: Clean quality multiplier (×1.2) labels Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved GSSoC: PR approved for scoring gssoc26 GSSoC 2026 contribution level:advanced GSSoC: Advanced difficulty (55 pts) quality:clean GSSoC: Clean quality multiplier (×1.2) type:bug GSSoC type bonus: bug fix type:feature GSSoC type bonus: new feature type:performance GSSoC type bonus: performance (+15 pts) type:testing GSSoC type bonus: tests (+10 pts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Implement Redis-based Caching Layer for GitHub API Rate Limit Mitigation

2 participants