Skip to content

feat: enhance rollup aggregation with dedup logic#1843

Merged
gustavobtflores merged 2 commits intokernelci:mainfrom
gustavobtflores:feat/tree-tests-rollup-deduplication
Apr 7, 2026
Merged

feat: enhance rollup aggregation with dedup logic#1843
gustavobtflores merged 2 commits intokernelci:mainfrom
gustavobtflores:feat/tree-tests-rollup-deduplication

Conversation

@gustavobtflores
Copy link
Copy Markdown
Contributor

@gustavobtflores gustavobtflores commented Apr 6, 2026

Description

Adds deduplication logic to the tree_tests_rollup aggregation and handle cases where a test's status is updated from null to a concrete value (pass/fail/etc.). Previously, these updates would incorrectly increment counters without adjusting the null count, leading to inflated totals.

Changes

  • Implemented deduplication logic in _process_tree_tests_rollup() to detect and handle existing processed entries with null statuses
  • Added get_rollup_key() helper function for consistent rollup key generation
  • Added comprehensive unit tests for rollup entry correction behavior

How to test

  1. Run the unit tests: python -m pytest backend/kernelCI_app/tests/unitTests/commands/process_pending_helpers_test.py -v
  2. Verify the deduplication logic handles null-to-status transitions correctly by checking test cases covering:
    • New tests with null status
    • New tests with concrete status
    • Existing null tests transitioning to pass/fail/skip/error statuses
    • Reprocessing with unchanged status (should be skipped)

Part of #1801

@gustavobtflores gustavobtflores self-assigned this Apr 6, 2026
@gustavobtflores gustavobtflores added Backend Most or all of the changes for this issue will be in the backend code. Ingester The issue relates to the ingester tool, including the command itself and related functions. labels Apr 6, 2026
@gustavobtflores gustavobtflores force-pushed the feat/tree-tests-rollup-deduplication branch from fe923af to de1d3d5 Compare April 7, 2026 12:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the tree_tests_rollup denormalized aggregation to correctly handle reprocessing when a test transitions from a NULL status to a concrete status, avoiding inflated totals by applying a “correction” delta (decrement null_tests, increment the concrete bucket, keep total_tests unchanged).

Changes:

  • Added a rollup-specific processed-item key (get_rollup_key) and used ProcessedListingItems to deduplicate rollup processing and detect NULL -> non-NULL transitions.
  • Extended rollup aggregation helpers to support correction deltas via is_correction / reprocess_test_ids.
  • Added unit tests validating correction behavior and the reprocess_test_ids pathway.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
backend/kernelCI_app/management/commands/process_pending_aggregations.py Adds rollup key generation and dedup/correction detection using ProcessedListingItems during rollup batching.
backend/kernelCI_app/management/commands/helpers/process_pending_helpers.py Implements correction delta behavior in rollup accumulation and threads reprocess_test_ids through aggregation.
backend/kernelCI_app/tests/unitTests/commands/process_pending_helpers_test.py Adds unit tests covering null -> non-null correction behavior and reprocess_test_ids handling.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

continue
else:
# null -> non-null: This is a correction (reprocess)
reprocess_test_ids.add(test.test_id)
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

In the null->non-null correction path (stored_status is None and new test.status is not None), the code marks the test for reprocessing but does not add an updated ProcessedListingItems entry to set status to the new non-null value. This leaves the processed row with status=None permanently, so any future re-ingestion of the same test_id will be treated as a correction again, repeatedly decrementing null_tests and skewing rollup totals. Add/update a ProcessedListingItems entry for the correction case (same listing_item_key) so bulk_create(update_conflicts=True) updates status away from None once corrected.

Suggested change
reprocess_test_ids.add(test.test_id)
reprocess_test_ids.add(test.test_id)
new_processed_entries.add(
ProcessedListingItems(
listing_item_key=rollup_key,
checkout_id=checkout_id,
status=test.status,
)
)

Copilot uses AI. Check for mistakes.
Comment on lines 105 to 110
def aggregate_tests_rollup(
ready_tests: Sequence[PendingTest],
test_builds_by_id: dict[str, Builds],
issues_map: dict[str, dict],
reprocess_test_ids: set[str] = set(),
) -> dict[tuple, dict]:
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

reprocess_test_ids uses a mutable default (set()). Even if this function doesn't mutate it today, mutable defaults are error-prone and make future edits risky. Prefer reprocess_test_ids: Optional[set[str]] = None and normalize to an empty set inside the function.

Copilot uses AI. Check for mistakes.
@gustavobtflores gustavobtflores force-pushed the feat/tree-tests-rollup-deduplication branch from de1d3d5 to 8aaa613 Compare April 7, 2026 13:36
new_processed_entries: set[ProcessedListingItems] = set()

for test in ready_tests:
rollup_key = rollup_keys_by_test_id[test.test_id]
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.

do we really need to precompute the rollup keys?
I believe we could compute them on demand (it would even avoid computation of keys where build id is not found)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

theoretically we should just receive tests here that have a build, the check below is mostly for checkout. we can move this after the check for sure, anyway

record[counter] += 1
else:
record[counter] += 1
record["total_tests"] += 1
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.

wouldn´t it be safer (less error prone) to make total_tests a derived value?
I believe it should be the sum of a small amount of fields, and wouldn´t make a significant impact on performance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we could make it computed in the database, as we process tests individually and within batches, it would be kinda bad to have this computation here

maybe something like: https://www.postgresql.org/docs/current/ddl-generated-columns.html

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.

Yeah, I second that

Copy link
Copy Markdown
Collaborator

@MarceloRobert MarceloRobert left a comment

Choose a reason for hiding this comment

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

LGTM. These things happen when we end up ingesting the same file multiple times such as when the ingester breaks for some reason

@gustavobtflores gustavobtflores added this pull request to the merge queue Apr 7, 2026
Merged via the queue into kernelci:main with commit 1e925d5 Apr 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend Most or all of the changes for this issue will be in the backend code. Ingester The issue relates to the ingester tool, including the command itself and related functions.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants