Skip to content

perf: use GraphQL batching for repo extras and contributor detail fetching #9

Description

@arun-gupta

Background

Follow-on to #8 (GraphQL batching for user/org repo fetching). The same bottleneck exists in two more pipeline steps: get_features_data() in get_repo_extras.py and get_contributor_data() in get_contributors.py. Both make one sequential REST call per repository or contributor — at UCSC scale that is tens of thousands of individual requests.

Why README and contributor data matter for affiliation scoring

The score-based classifier (SBC) uses three signals:

Signal Without README/contributors With README/contributors
repository_score full_name + description + homepage only + full README text — university mentions, course names, faculty/lab names
organization_score org name/description keywords same
contributor_score 0 — no data @ucsc.edu email domains, bios, company fields

In a test run on UCSC (24,919 repos):

  • Without README/contributor data: 64 repos pass the 0.7 affiliation threshold
  • Expected with README/contributor data: significantly more — repos with no university keywords in name/description but @ucsc.edu contributor emails or "UC Santa Cruz" in the README jump from score 0 → high

Score distribution without README/contributor data (UCSC, 24,919 repos):

mean:  0.039
std:   0.109
> 0.7: 64 repos
> 0.5: 192 repos
> 0.3: 727 repos

Current bottleneck

get_features_data()get_repo_extras.py

  • GET /repos/{owner}/{repo}/readme × N repos (one call per repo)
  • GET /repos/{owner}/{repo}/releases × N repos
  • GET /repos/{owner}/{repo}/community/profile × N repos
  • At 24,919 repos: ~75,000 sequential REST calls for the three main features

get_contributor_data()get_contributors.py

  • GET /repos/{owner}/{repo}/contributors × N repos (get logins)
  • GET /users/{login} × M contributors (get bio/email/company/location)
  • At 24,919 repos with avg ~5 contributors: ~125,000+ sequential REST calls for contributor details alone

Proposed GraphQL optimisations

README + release downloads: batch 50 repos per query

query BatchRepoExtras {
  r0: repository(owner: "ucsd", name: "triton") {
    object(expression: "HEAD:README.md") { ... on Blob { text } }
    releases(first: 20) {
      nodes { releaseAssets(first: 10) { nodes { downloadCount } } }
    }
  }
  r1: repository(owner: "ucsc", name: "some-repo") { ... }
  ...
}
  • Reduces ~50,000 REST calls → ~500 GraphQL requests (~100× fewer)
  • Case-sensitivity caveat: GraphQL object(expression: "HEAD:README.md") is case-sensitive. Use REST fallback for repos where GraphQL returns null (handles readme.md, Readme.md, etc.)

Contributor details: batch 50 users per query (same pattern as #8)

query BatchContributorDetails {
  u0: user(login: "alice") { name bio location company email }
  u1: user(login: "bob")   { name bio location company email }
  ...
}

Contributor list: keep as REST

  • GET /repos/{owner}/{repo}/contributors lists git commit authors
  • GraphQL mentionableUsers / collaborators are not equivalent
  • No change here

Impact summary

Step Current REST calls (UCSC) With GraphQL batching Speedup
README + releases ~50,000 ~500 ~100×
Contributor details ~125,000+ ~2,000 ~50×
Contributor list ~25,000 ~25,000 (unchanged)
Total ~200,000 ~27,500 ~7× overall

Implementation plan

  1. Add _build_repo_extras_batch_query(repos) to repo_scraping_utils.py — batches 50 (owner, name) pairs per query, fetches README text + release asset download counts
  2. Add _build_contributor_details_batch_query(logins) — batches 50 contributor logins per query (same pattern as existing user batching)
  3. Update get_features_data() in get_repo_extras.py to use GraphQL batch path with REST fallback for README case-sensitivity misses
  4. Update get_contributor_data() in get_contributors.py to use GraphQL batch path for contributor detail fetching; keep REST for contributor list

Notes

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions