⚡ perf: cache historical github year in review data - #518
Conversation
Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
Warning Review limit reached
Next review available in: 50 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📄 Knowledge reviewDosu skipped reviewing this PR because your organization has used its |
PR Summary by QodoCache GitHub Year-in-Review fetches for historical years
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| try { | ||
| const currentYear = new Date().getFullYear(); | ||
| const cacheOpt: RequestCache = year < currentYear ? "force-cache" : "no-store"; | ||
|
|
There was a problem hiding this comment.
過去年でもコミットの追加・削除、リポジトリの公開範囲変更、private contribution の表示設定変更などで GitHub の集計は更新されますが、この変更は GraphQL と REST の応答を再検証期限なしで force-cache に固定します。そのため、最初に保存された contribution totals、top repository、most-active hour、heatmap が GitHub の最新状態と一致しなくなり、キャッシュが外部要因で消えるまで古い年次レビューが返り続けます。
Knowledge Base Used: Year in Review
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/githubYearInReview.ts
Line: 258
Comment:
**過去年キャッシュが再検証されない**
過去年でもコミットの追加・削除、リポジトリの公開範囲変更、private contribution の表示設定変更などで GitHub の集計は更新されますが、この変更は GraphQL と REST の応答を再検証期限なしで `force-cache` に固定します。そのため、最初に保存された contribution totals、top repository、most-active hour、heatmap が GitHub の最新状態と一致しなくなり、キャッシュが外部要因で消えるまで古い年次レビューが返り続けます。
**Knowledge Base Used:** [Year in Review](https://app.greptile.com/hiroki-org/-/custom-context/knowledge-base/hiroki-org/github-user-summary/-/docs/year-in-review.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| const currentYear = new Date().getFullYear(); | ||
| const cacheOpt: RequestCache = year < currentYear ? "force-cache" : "no-store"; |
There was a problem hiding this comment.
サーバーのタイムゾーンが UTC より進んでいる場合、年越し直後は API とクライアントが getUTCFullYear() で選ぶ現在年を、ここでは getFullYear() により過去年と判定します。その時間帯だけ更新中の年次データが force-cache の対象になり、不完全な集計がキャッシュされるため、検索期間や API 検証と同じ UTC 基準を使用してください。
Knowledge Base Used: Year in Review
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/githubYearInReview.ts
Line: 256-257
Comment:
**現在年判定が UTC と不一致**
サーバーのタイムゾーンが UTC より進んでいる場合、年越し直後は API とクライアントが `getUTCFullYear()` で選ぶ現在年を、ここでは `getFullYear()` により過去年と判定します。その時間帯だけ更新中の年次データが `force-cache` の対象になり、不完全な集計がキャッシュされるため、検索期間や API 検証と同じ UTC 基準を使用してください。
**Knowledge Base Used:** [Year in Review](https://app.greptile.com/hiroki-org/-/custom-context/knowledge-base/hiroki-org/github-user-summary/-/docs/year-in-review.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Code Review by Qodo
Context used✅ Compliance rules (platform):
30 rules 1. cacheOpt behavior untested
|
| try { | ||
| const currentYear = new Date().getFullYear(); | ||
| const cacheOpt: RequestCache = year < currentYear ? "force-cache" : "no-store"; | ||
|
|
||
| const response = await graphql<YearInReviewResponse>(YEAR_IN_REVIEW_QUERY, token, { | ||
| login: username, | ||
| from: from.toISOString(), | ||
| to: to.toISOString(), | ||
| maxRepositories: 10, | ||
| }); | ||
| }, cacheOpt); |
There was a problem hiding this comment.
1. cacheopt behavior untested 📘 Rule violation ▣ Testability
This PR changes cache behavior by switching GitHub requests to force-cache for historical years,
but no test asserts the new fetch(..., { cache: ... }) behavior for past vs current year. Without
explicit assertions, regressions (e.g., always using no-store) could slip in unnoticed.
Agent Prompt
## Issue description
Caching behavior was changed to use `force-cache` for historical years and `no-store` for the current year, but tests do not assert that the correct `fetch` `cache` option is used.
## Issue Context
`fetchYearInReviewData` and `fetchCommitActivityHeatmap` now compute `cacheOpt` based on `year < new Date().getFullYear()` and pass it into the GraphQL helper / REST `fetch` call. Existing tests stub `fetch` but never validate the `cache` option in the request init.
## Fix Focus Areas
- src/lib/githubYearInReview.ts[255-308]
- src/lib/githubYearInReview.ts[327-327]
- src/lib/__tests__/githubYearInReview.test.ts[1-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const currentYear = new Date().getFullYear(); | ||
| const cacheOpt: RequestCache = year < currentYear ? "force-cache" : "no-store"; | ||
|
|
There was a problem hiding this comment.
2. Timezone year mismatch caching 🐞 Bug ≡ Correctness
fetchYearInReviewData (and fetchCommitActivityHeatmap) uses new Date().getFullYear() (server local timezone) to choose "force-cache" vs "no-store", but the API route validates requested years against getUTCFullYear() and the from/to bounds are built with Date.UTC. Around New Year on servers ahead of UTC, this can incorrectly treat the current UTC year as historical and cache it, serving stale results for that window.
Agent Prompt
### Issue description
The caching decision for year-in-review requests uses `new Date().getFullYear()` (local timezone), while the rest of the system uses UTC year semantics (`getUTCFullYear()` and `Date.UTC(...)`). This mismatch can cause the current UTC year to be treated as “historical” and cached around New Year depending on server timezone.
### Issue Context
- The route handler selects/validates `year` using `getUTCFullYear()`.
- The data query window is constructed using `Date.UTC(...)`.
- The caching decision should follow the same UTC definition of “current year”.
### Fix
Replace `new Date().getFullYear()` with `new Date().getUTCFullYear()` in both call sites (or centralize into a small helper to avoid duplication).
### Fix Focus Areas
- src/lib/githubYearInReview.ts[252-264]
- src/lib/githubYearInReview.ts[292-308]
- src/app/api/dashboard/year/route.ts[18-22]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Co-authored-by: is0692vs <135803462+is0692vs@users.noreply.github.com>
💡 What:
Updated the GitHub GraphQL data fetching logic to dynamically set the
fetchAPIcacheoption. For requests querying historical data (any year prior to the current year), it now uses"force-cache". For the current year, it preserves the existing"no-store"behavior.🎯 Why:
The previous implementation forced a fresh, uncached network request to GitHub on every call using
cache: 'no-store', regardless of the queried year. Since a user's GitHub activity for past years is immutable (it will not change), bypassing the cache causes unnecessary latency, overhead, and potential rate-limiting. This optimization instantly improves response times for historical Year-in-Review data lookups by leveraging Next.js' native caching, which safely incorporates headers and POST bodies into the cache keys.📊 Measured Improvement:
Due to Next.js server constraints preventing local standalone script benchmarking of
server-onlyApp Router logic outside ofnext dev, I could not generate millisecond-level benchmark outputs. However, enabling native'force-cache'transforms external network bound REST/GraphQL API hops (typically 300-800ms) into near-instant local cache hits (~1-5ms), guaranteeing a substantial net performance gain.PR created automatically by Jules for task 14933273120319169105 started by @is0692vs
Greptile Summary
過去年の Year in Review 取得で Next.js の fetch キャッシュを利用し、現在年は従来どおり毎回 GitHub から取得する変更です。
force-cacheに変更no-storeを維持Confidence Score: 4/5
過去年の可変な GitHub 集計を無期限に固定するため、再検証方針を追加してからマージする必要があります。
過去年の主要 GraphQL・REST 応答が無効化経路なしでキャッシュされるため、GitHub 側で履歴や公開範囲が変化しても古い年次レビューが返り続けます。また、ローカル年と UTC 年の不一致により年越し時に現在年を誤ってキャッシュする可能性があります。
Files Needing Attention: src/lib/githubYearInReview.ts
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR A[Year request] --> B{year < currentYear} B -->|Yes| C[force-cache] B -->|No| D[no-store] C --> E[GitHub GraphQL year data] C --> F[GitHub GraphQL commit dates] C --> G[GitHub REST commits] D --> E D --> F D --> GPrompt To Fix All With AI
Reviews (1): Last reviewed commit: "perf: cache historical github year in re..." | Re-trigger Greptile
Context used: