Parent: #1936
Problem
A recently-merged fix (#2527) added a durable repo+PR+head-SHA cache for a PR's changed files, cutting redundant GET /pulls/{n}/files calls. Live rate-limit observation data during a near-exhaustion window showed two sibling routes as even larger contributors that the same fix deliberately left uncached:
- A bare
GET /pulls/{n} (PR state/head/mergeable-state) fetch, implemented as four separate near-identical helper functions with no caching or cross-call coalescing at all, called from many independent sites (readiness checks, freshness guards, the maintenance planner, and once per planned auto-maintain action) — several of which fire multiple times for the same PR within one review pass.
GET /pulls/{n}/reviews, which was explicitly left out of the earlier fix ("reviews are more volatile than files" — true at a fixed head, but reviews only actually change on a pull_request_review webhook, not on every sweep tick).
Together these two routes were the largest and third-largest contributors observed in a live rate-limit trough, larger than the files route the earlier fix addressed.
Requirements
- Add a short-TTL or event-invalidated cache for the bare PR read, keyed by repo+PR, refreshed by the relevant webhook types (synchronize/closed/reopened) and read by the freshness-guard/readiness/maintenance-planner call sites — while explicitly preserving any call site that intentionally bypasses caching because it sits at a mutation-act boundary (there is at least one such site today, documented in its own code comment; do not weaken it).
- Extend the existing head-SHA file-cache pattern to reviews, but invalidate on
pull_request_review webhook events (submitted/dismissed/edited) rather than on head-SHA change, since reviews are independent of the head.
- Preserve exact current behavior for any call site that must observe a live, uncached read (act-boundary merge/close decisions).
Deliverables
- A cache for the bare PR-state read, applied to the read-only call sites (freshness guards, readiness checks) while leaving the documented act-boundary call site live.
- A head-SHA/review-webhook-scoped cache for
fetchPullRequestReviews, following the same storage pattern as the existing files cache.
- Tests mirroring the existing files-cache test suite: cache miss on first read, cache hit on unchanged state, cache invalidation on the relevant webhook, and a regression test proving act-boundary reads are never served from cache.
Acceptance criteria
- Both routes' call volume drops materially for repeat reads of an unchanged PR, verified via the existing bounded-caller metrics pattern.
- No regression in any decision that depends on a live PR state (merge eligibility, close eligibility, mergeable-state gating).
- Full local gate green with near-100% patch coverage on the new caching logic, matching the standard for this repo's Codecov gate.
Expected outcome
The GitHub REST budget consumed by routine PR-state and review polling drops by a similar order of magnitude to what the files cache already achieved, without weakening any correctness-critical live read.
Parent: #1936
Problem
A recently-merged fix (#2527) added a durable repo+PR+head-SHA cache for a PR's changed files, cutting redundant
GET /pulls/{n}/filescalls. Live rate-limit observation data during a near-exhaustion window showed two sibling routes as even larger contributors that the same fix deliberately left uncached:GET /pulls/{n}(PR state/head/mergeable-state) fetch, implemented as four separate near-identical helper functions with no caching or cross-call coalescing at all, called from many independent sites (readiness checks, freshness guards, the maintenance planner, and once per planned auto-maintain action) — several of which fire multiple times for the same PR within one review pass.GET /pulls/{n}/reviews, which was explicitly left out of the earlier fix ("reviews are more volatile than files" — true at a fixed head, but reviews only actually change on apull_request_reviewwebhook, not on every sweep tick).Together these two routes were the largest and third-largest contributors observed in a live rate-limit trough, larger than the files route the earlier fix addressed.
Requirements
pull_request_reviewwebhook events (submitted/dismissed/edited) rather than on head-SHA change, since reviews are independent of the head.Deliverables
fetchPullRequestReviews, following the same storage pattern as the existing files cache.Acceptance criteria
Expected outcome
The GitHub REST budget consumed by routine PR-state and review polling drops by a similar order of magnitude to what the files cache already achieved, without weakening any correctness-critical live read.