Skip to content

Eliminate lazy repository FK fetches in worker tasks and push health_summary - #9785

Open
camd wants to merge 1 commit into
masterfrom
camd/select-related-repository
Open

Eliminate lazy repository FK fetches in worker tasks and push health_summary#9785
camd wants to merge 1 commit into
masterfrom
camd/select-related-repository

Conversation

@camd

@camd camd commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Problem

Production GCP logs show chained tracebacks of this shape:

File "django/db/models/fields/related_descriptors.py", line 239, in __get__
    rel_obj = self.field.get_cached_value(instance)
  File "django/db/models/fields/mixins.py", line 37, in get_cached_value
    return instance._state.fields_cache[self.cache_name]
KeyError: 'repository'

That KeyError is Django's normal FK cache-miss path: it is caught inside ForwardManyToOneDescriptor.__get__, which then fetches the Repository row from the DB. When that one-off fetch fails, the failure is chained onto the KeyError ("During handling of the above exception...").

The trigger is model instances loaded without select_related("repository") in long-running celery tasks: the instance is fetched at task start, the task then spends a long time on other work (e.g. downloading logs over HTTP), and only afterwards touches .repository — by which point the connection backing the lazy fetch can have gone stale, so the task blows up mid-work instead of failing fast at task start under the normal retry path.

Fix

Add select_related for the repository FK chain at the entry-point querysets:

  • log-parser task: JobLog queryset gets select_related("job__repository") — the lazy accesses are on job_log.job.repository (two lazy hops) in post_log_artifacts, failureline.py, and the error-summary path
  • ingest-perfherder-data task: same job__repository treatment; covers etl/perf.py's job.repository.performance_alerts_enabled reads
  • generate-alerts task: signature fetched with select_related("repository", "framework") — both are read repeatedly in generate_new_alerts_in_series, including inside the select_for_update transaction added in Bug 2035204 - Prevent creation of duplicate AlertSummary rows for the same push #9754
  • check_and_mark_intermittent: job fetched with select_related("repository", "job_type", "push") — all three FKs are read
  • classification loader: the Job lookup (Job.__str__ reads self.repository when interpolated into a log line) and get_push's Push lookup now select_related
  • push health_summary API: the revision= branch gets the select_related("repository") its author= sibling branch already had

Besides removing the failure mode, this drops a query (or several) per task/request.

Testing

Ran the backend suites for every touched module — tests/log_parser/, tests/etl/test_classification_loader.py, test_load_artifacts.py, test_perf_data_load.py, tests/webapp/api/test_push_api.py, tests/perfalert/test_alerts.py: 231 passed, 1 pre-existing xfail. No new tests: the change is query-shape only and all modified paths are covered by existing functional tests.

…summary

Production logs show chained tracebacks (KeyError: 'repository' as
__context__) from Django's ForwardManyToOneDescriptor: model instances
loaded without select_related trigger a one-off Repository fetch deep
inside long-running celery tasks, where the DB connection may have gone
stale since the instance was first loaded (e.g. after slow log
downloads), so the lazy fetch fails mid-task instead of failing fast at
task start under the normal retry path.

Add select_related for the repository FK chain at the task entry-point
querysets (log parser, perfherder ingestion, alert generation,
classification loader, artifact loading) and in the health_summary
revision branch, which was missing the select_related its author branch
already had. This also drops a query per task/request.
@netlify

netlify Bot commented Aug 15, 2026

Copy link
Copy Markdown

Deploy Preview for treeherder ready!

Name Link
🔨 Latest commit f5a6091
🔍 Latest deploy log https://app.netlify.com/projects/treeherder/deploys/6a80e0366a5a18000826f005
😎 Deploy Preview https://deploy-preview-9785--treeherder.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.42%. Comparing base (07be574) to head (f5a6091).

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #9785       +/-   ##
===========================================
+ Coverage   69.15%   83.42%   +14.26%     
===========================================
  Files         637      638        +1     
  Lines       38505    38537       +32     
  Branches     3466     3472        +6     
===========================================
+ Hits        26630    32150     +5520     
+ Misses      11481     6236     -5245     
+ Partials      394      151      -243     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

2 participants