Skip to content

Add ETag conditional-request cache to cut GitHub API usage#468

Closed
ianrohde wants to merge 1 commit into
masterfrom
etag-request-cache
Closed

Add ETag conditional-request cache to cut GitHub API usage#468
ianrohde wants to merge 1 commit into
masterfrom
etag-request-cache

Conversation

@ianrohde

Copy link
Copy Markdown
Contributor

Draft for option 1 in #467.

What

Adds an in-process ETag conditional-request cache to the Octokit client. A conditional request returning 304 Not Modified does not count against the primary REST rate limit (docs). lib/etag-cache.js wraps the Octokit request hook to:

  • remember each GET response's ETag,
  • replay it via If-None-Match on the next identical request,
  • serve the cached body when GitHub responds 304.

Why

On boot, app.js runs refresh.openPulls(), sending every open pull (across all repos) through git-manager.parse() — ~8–15 REST calls each. Almost none have changed since the last run, so on a restart this re-fetch is mostly wasted quota and can blow the 5000/hr limit (the incident in #467). With the cache, unchanged resources return 304 and cost nothing.

How

  • installEtagCache(octokit) is called once in git-manager.js, right after the client is built (composes with the existing throttling plugin).
  • GETs only; other methods pass through untouched.
  • Bounded, insertion-ordered Map used as a rough LRU (default 2000 entries), keyed by the resolved method + url so paginated pages cache separately.

Test plan

  • node --test test/*.test.js — new test/etag-cache.test.js drives a real Octokit with a stub fetch, asserting the 200→304 replay path and that the cached ETag is sent via If-None-Match; non-GETs send no conditional header.
  • npx eslint on changed files — clean.
  • Manual: deploy, restart, confirm open-pull resync produces 304s (debug pulldasher:etag-cache) and that core rate-limit usage drops vs. a cold start.

Notes / open questions for #467

On boot, refresh.openPulls() re-fetches every open pull (~8-15 REST
calls each) even though almost none changed since the last run, which
can drain the hourly quota and take the app down (#467).

A conditional request returning 304 Not Modified does not count against
the primary rate limit. installEtagCache wraps the Octokit request hook
to remember each GET's ETag and replay it via If-None-Match, so
unchanged resources cost no quota. Bounded LRU keyed by resolved
method+url (paginated pages key separately).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ianrohde ianrohde marked this pull request as ready for review June 18, 2026 01:38
@ianrohde

Copy link
Copy Markdown
Contributor Author

I don't think this is necessary

@ianrohde ianrohde closed this Jun 19, 2026
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.

1 participant