Skip to content

TRT-2821: Optimize GetJobRunTestsCountByLookback using cumulative summaries - #3876

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
mstaeble:optimize-lookback-count
Aug 6, 2026
Merged

TRT-2821: Optimize GetJobRunTestsCountByLookback using cumulative summaries#3876
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
mstaeble:optimize-lookback-count

Conversation

@mstaeble

@mstaeble mstaeble commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace the single COUNT(DISTINCT) query against prow_job_run_tests (the largest table, ~70M rows in a 14-day window) with two targeted queries:
    • Job run count from prow_job_runs directly (one row per run, indexed on timestamp): ~50ms
    • Test ID count using per-release cumulative summary self-joins run concurrently via errgroup (4 workers): ~2s
  • Total wall-clock drops from ~3 minutes to ~2 seconds on staging

Benchmark results (staging, 3 iterations)

Query Before (prod) After (staging)
14-day lookback 219s ~2s
9-day lookback 160s ~2s

Approach

The old query scanned prow_job_run_tests with two COUNT(DISTINCT) aggregates (no release filter, hitting all partitions). The new approach:

  1. Counts job runs from prow_job_runs (much smaller table, indexed timestamp)
  2. Gets the release list from release_definitions
  3. For each release, queries test_cumulative_summaries with a self-join on two dates (window end vs window start minus one day), pre-aggregating by test_id with GROUP BY + SUM before joining, so only ~14K aggregated rows join instead of ~2M raw rows
  4. Merges distinct test IDs across releases in Go via a channel and sets.New[int64]()

Pinning each query to a single release is critical: without it, the Postgres planner spends 4+ seconds just evaluating ~3,600 sub-partitions (36 releases x ~100 date ranges). A single global query takes ~7s (4.4s planning + 2.7s execution), while per-release queries run concurrently in ~2s total.

Test plan

  • gofmt -w and go vet pass
  • Benchmarked on staging via Test_BenchmarkIndividual/TestCountsByLookback (3 iterations each)
  • Benchmarked individual per-release queries via psql on prod
  • Verified result counts match between old and new implementations
  • CI passes

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability when retrieving test counts over a lookback period.
    • Ensured accurate deduplication across releases and multiple jobs.
    • Excluded deleted, out-of-window, and zero-change runs from counts.
    • Added validation for invalid lookback periods and unavailable database connections.
  • Performance

    • Release data lookups can now run concurrently, improving response times.
  • Monitoring

    • Added structured operation logging and duration metrics for improved visibility.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: automatic mode

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 5, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 5, 2026
@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci-robot

openshift-ci-robot commented Aug 5, 2026

Copy link
Copy Markdown

@mstaeble: This pull request references TRT-2821 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Replace the single COUNT(DISTINCT) query against prow_job_run_tests (the largest table, ~70M rows in a 14-day window) with two targeted queries:
  • Job run count from prow_job_runs directly (one row per run, indexed on timestamp): ~50ms
  • Test ID count using per-release cumulative summary self-joins run concurrently via errgroup (4 workers): ~9s
  • Total wall-clock drops from ~3 minutes to ~9 seconds on staging (benchmarked against prod as well)

Benchmark results (staging, 3 iterations)

Query Before (prod) After (staging)
14-day lookback 219s 9.1s
9-day lookback 160s 9.7s

Approach

The old query scanned prow_job_run_tests with two COUNT(DISTINCT) aggregates (no release filter, hitting all partitions). The new approach:

  1. Counts job runs from prow_job_runs (much smaller table, indexed timestamp)
  2. Gets the release list from release_definitions
  3. For each release, queries test_cumulative_summaries with a self-join on two dates (window end vs window start minus one day), pinning to a single release so Postgres prunes to one date sub-partition per side
  4. Merges distinct test IDs across releases in Go via a channel and sets.New[int64]()

A SQL UNION ALL alternative was benchmarked but ran ~10x slower (102s) because all subqueries execute sequentially within a single DB connection.

Test plan

  • gofmt -w and go vet pass
  • Benchmarked on staging via Test_BenchmarkIndividual/TestCountsByLookback (3 iterations each)
  • Benchmarked individual per-release queries via psql on prod
  • Verified result counts match between old and new implementations
  • CI passes

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@mstaeble, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 23 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 374de7cd-adb6-4c5a-9ac0-90fb6f6ddbb7

📥 Commits

Reviewing files that changed from the base of the PR and between 5da7ac2 and eeccb8e.

📒 Files selected for processing (2)
  • pkg/api/tests.go
  • test/integration/lookback_count_test.go

Walkthrough

GetJobRunTestsCountByLookback now counts job runs directly and derives distinct test IDs from per-release cumulative summaries. It limits concurrent release queries, aggregates results, validates errors, and records query metrics.

Changes

Lookback test count

Layer / File(s) Summary
Validate and count job runs
pkg/api/tests.go
The method validates the database connection and lookback duration. It uses civil-date boundaries and counts non-deleted job runs from prow_job_runs.
Aggregate release summaries
pkg/api/tests.go
The method lists releases, queries cumulative summaries with bounded concurrency, filters positive deltas, deduplicates test IDs, and logs both computed counts.
Validate lookback behavior
test/integration/lookback_count_test.go
Integration tests cover release deduplication, delta handling, job-run filtering, multi-job aggregation, empty data, and invalid inputs.

Estimated code review effort: 4 (Complex) | ~30 minutes

Possibly related PRs

Suggested labels: lgtm

Suggested reviewers: dgoodwin, petr-muller

🚥 Pre-merge checks | ✅ 19 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Go Error Handling ⚠️ Warning GetJobRunTestsCountByLookback checks dbc but dereferences dbc.DB at lines 395, 409, and 431 without checking dbc.DB; a nonnil wrapper with nil DB can panic. Check dbc == nil || dbc.DB == nil before any database use and return a contextual error.
Single Responsibility And Clear Naming ⚠️ Warning GetJobRunTestsCountByLookback mixes validation, job-run counting, release lookup, concurrent raw SQL, ID merging, and logging in one method. Extract focused helpers for job-run counting, release test-ID querying, and aggregation; keep the exported method as orchestration.
✅ Passed checks (19 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary optimization using cumulative summaries.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Sql Injection Prevention ✅ Passed Added queries use fixed SQL and GORM placeholders for timestamps, releases, and dates; release is only formatted in an error message, and tests use model inserts.
Excessive Css In React Should Use Styles ✅ Passed The PR changes only two Go files; neither contains JSX, React style props, or useStyles usage. The React inline-CSS check is not applicable.
Test Coverage For New Features ✅ Passed Eight tracked integration tests exercise the modified function, covering release deduplication, cumulative deltas, missing history, run-window/deletion rules, empty releases, invalid input, and nil...
Feature Documentation ✅ Passed The PR changes an internal lookback-count implementation and tests; the only docs/features file documents the unrelated symptoms and labels feature, so no relevant feature doc needs updating.
Stable And Deterministic Test Names ✅ Passed The added tests use standard Go Test functions, not Ginkgo declarations. All eight names are static descriptive strings with no runtime values, dates, UUIDs, pods, nodes, namespaces, or IPs.
Test Structure And Quality ✅ Passed The added tests use standard testing.T and testify, not Ginkgo; Ginkgo-specific requirements do not apply, and NewTestDB registers database cleanup with t.Cleanup.
Microshift Test Compatibility ✅ Passed The PR adds ordinary Go integration tests, not Ginkgo e2e tests; they use PostgreSQL fixtures and no MicroShift-unavailable OpenShift APIs or assumptions.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The added tests use Go testing with PostgreSQL fixtures only; they add no Ginkgo e2e tests or multi-node/HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The pull request changes only Go API logic and integration tests; it adds no deployment manifests, controllers, operators, or scheduling constraints.
Ote Binary Stdout Contract ✅ Passed The patch adds no stdout writes or suite/process setup; its only new output is logrus logging in the API function, which uses stderr by default.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The added tests use standard testing.T integration tests, not Ginkgo e2e tests, and contain no IPv4 assumptions or external network access.
No-Weak-Crypto ✅ Passed The patch adds database counting and integration fixtures only; searches found no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret-token comparisons.
Container-Privileges ✅ Passed The commit changes only Go source and tests. The diff adds no container/Kubernetes manifests or flagged privilege settings; existing e2e settings are non-privileged.
No-Sensitive-Data-In-Logs ✅ Passed New logs contain only lookbackDays, aggregate counts, and query duration; no passwords, tokens, PII, hostnames, or customer data are logged.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 5, 2026
@mstaeble

mstaeble commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/api/tests.go`:
- Around line 384-460: Add regression coverage for the redesigned count
function, exercising multiple releases with overlapping test IDs and
date-boundary data. Verify the result globally deduplicates IDs and counts only
rows whose prefix-sum difference is positive, while preserving expected job-run
counts and successful concurrent aggregation.
- Around line 413-450: Update the concurrent release-processing flow around the
errgroup worker and testIDs aggregation so each worker inserts its
releaseTestIDs into the shared deduplicated testIDs set under a mutex before
returning. Initialize the set and mutex before launching workers, remove the
result channel and post-Wait aggregation, and preserve the existing
g.SetLimit(4) and error handling.
- Around line 392-395: Validate dbc for nil at the start of the surrounding test
function, before the prow_job_runs query dereferences dbc.DB, and return the
function’s existing error result with an appropriate error when it is nil.
Preserve the current query behavior for non-nil database clients.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c9f680b-2ea7-4afd-811c-78c24a38b77b

📥 Commits

Reviewing files that changed from the base of the PR and between 59a59fe and 3ff9ca0.

📒 Files selected for processing (1)
  • pkg/api/tests.go

Comment thread pkg/api/tests.go Outdated
Comment thread pkg/api/tests.go
Comment thread pkg/api/tests.go Outdated
@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from 3ff9ca0 to 9383da7 Compare August 5, 2026 14:14
@mstaeble mstaeble changed the title TRT-2821: Optimize GetJobRunTestsCountByLookback from ~3min to ~6s TRT-2821: Optimize GetJobRunTestsCountByLookback using cumulative summaries Aug 5, 2026
@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from 9383da7 to e1f3394 Compare August 5, 2026 17:16
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from e1f3394 to ca2d801 Compare August 5, 2026 17:24
@openshift-ci openshift-ci Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label Aug 5, 2026
@mstaeble
mstaeble marked this pull request as ready for review August 5, 2026 18:00
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 5, 2026
@openshift-ci
openshift-ci Bot requested review from dgoodwin and petr-muller August 5, 2026 18:02
@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from ca2d801 to 2747b9b Compare August 5, 2026 18:58
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/integration/lookback_count_test.go (1)

80-98: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add negative-delta coverage.

This test verifies that a zero delta is excluded. It does not verify that a negative delta is excluded. A change from > 0 to != 0 would pass this test and violate the positive-delta contract.

Add a case where the end prefix sum is lower than the start prefix sum. Assert that the test ID count is zero.

As per coding guidelines, “New or modified functionality should include test coverage.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integration/lookback_count_test.go` around lines 80 - 98, Extend
TestLookbackCount_ZeroDeltaExcluded with a fixture whose end-date prefix sum is
lower than its start-date prefix sum, then assert GetJobRunTestsCountByLookback
returns a zero test ID count for that negative-delta case. Preserve the existing
zero-delta and positive-delta coverage, ensuring the test validates that only
strictly positive deltas are counted.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/integration/lookback_count_test.go`:
- Around line 60-61: Remove the UTC-midnight race in the lookback count tests by
making fixture setup and GetJobRunTestsCountByLookback use a stable date pair.
Prefer injecting a fixed clock through the API test seam; otherwise seed
fixtures for both dates that can result from the separate UTC date calculations.
Apply the same change to all today/startMinusOne calculations in the affected
tests.

---

Nitpick comments:
In `@test/integration/lookback_count_test.go`:
- Around line 80-98: Extend TestLookbackCount_ZeroDeltaExcluded with a fixture
whose end-date prefix sum is lower than its start-date prefix sum, then assert
GetJobRunTestsCountByLookback returns a zero test ID count for that
negative-delta case. Preserve the existing zero-delta and positive-delta
coverage, ensuring the test validates that only strictly positive deltas are
counted.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 51592e48-fbf7-47f9-8cab-2cf74f5a1cd7

📥 Commits

Reviewing files that changed from the base of the PR and between 5da7ac2 and 2747b9b.

📒 Files selected for processing (2)
  • pkg/api/tests.go
  • test/integration/lookback_count_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/api/tests.go

Comment thread test/integration/lookback_count_test.go Outdated
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from 2747b9b to 1baefd4 Compare August 5, 2026 19:32
@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from 1baefd4 to 9f61222 Compare August 5, 2026 19:34
Replace the single COUNT(DISTINCT) query against prow_job_run_tests
(the largest table) with two targeted queries:

1. Job run count from prow_job_runs directly (one row per run,
   indexed on timestamp) instead of COUNT(DISTINCT prow_job_run_id)
   over millions of test rows.

2. Test ID count using per-release cumulative summary self-joins
   run concurrently via errgroup. Pinning each query to a single
   release enables partition pruning to a single date sub-partition
   per side of the join, avoiding the cross-partition scan that
   causes 4+ seconds of planning time alone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mstaeble
mstaeble force-pushed the optimize-lookback-count branch from 9f61222 to eeccb8e Compare August 5, 2026 19:35
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@neisw

neisw commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

/test e2e
/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 5, 2026
@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mstaeble, neisw

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

/retest-required

Remaining retests: 0 against base HEAD ff252ad and 2 for PR HEAD eeccb8e in total

@mstaeble

mstaeble commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

/test e22

@mstaeble

mstaeble commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

/test e2e

@openshift-ci

openshift-ci Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@mstaeble: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@openshift-merge-bot
openshift-merge-bot Bot merged commit 5a43ecb into openshift:main Aug 6, 2026
10 checks passed
@mstaeble
mstaeble deleted the optimize-lookback-count branch August 7, 2026 00:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants