Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Chat diff-status worker re-downloads unchanged PRs instead of using conditional requests #27627

Copy link
Copy link

Description

@joshfree
Issue body actions

Summary

The chat diff-status worker polls open pull requests on a fixed 10s interval and re-downloads the full JSON body on every tick, even when nothing changed. The GitHub client (coderd/externalauth/gitprovider/github.go) never sends If-None-Match / ETag, so GitHub always returns a full 200 OK instead of a cheap 304 Not Modified.

Why it matters

304 responses don't count against GitHub's primary rate limit; full 200s do. Every unchanged poll needlessly burns a user's/installation's API quota — multiplied by the number of tracked PRs and the 10s cadence. On busy instances this worker can quietly exhaust the quota that the same token needs for interactive Git and API operations, so users hit rate-limit errors and stalls elsewhere in Coder. Adopting conditional requests fixes that with no behavior change — unchanged PRs revalidate for free, and only real changes transfer a body.

Where

  • coderd/x/gitsync/worker.go: defaultInterval = 10 * time.Second, defaultBatchSize = 50.
  • Per refresh (all full 200s today): ResolveBranchPullRequestGET /repos/{owner}/{repo}/pulls?...; FetchPullRequestStatusGET /repos/{owner}/{repo}/pulls/{n} and .../pulls/{n}/reviews?per_page=100.
  • githubProvider.decodeJSON sets Accept, X-GitHub-Api-Version, and a bearer token but no If-None-Match, and keeps no ETag cache. The worker is a long-lived singleton, so an in-process cache persists across ticks.

Proposed fix

Add a small, concurrency-safe, bounded ETag+body cache and wire it into decodeJSON: key on request URL + a hash of the token (never serve one token's response under another; don't retain raw tokens); send If-None-Match when an ETag is cached; on 304 decode the cached body; on 200 cache {etag, body} under a size cap. Bound by entry count and per-body size. Leave the raw-diff path (fetchDiff) out of scope to avoid caching large bodies.

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.