Skip to content

[2.7 backport] AAP-57614 fix: dispatch save_indirect_host_entries from artifacts_handler#16365

Draft
djulich wants to merge 4 commits intodevelfrom
AAP-57614-fix-artifacts-handler-dispatch-devel
Draft

[2.7 backport] AAP-57614 fix: dispatch save_indirect_host_entries from artifacts_handler#16365
djulich wants to merge 4 commits intodevelfrom
AAP-57614-fix-artifacts-handler-dispatch-devel

Conversation

@djulich
Copy link
Copy Markdown
Contributor

@djulich djulich commented Mar 22, 2026

Jira

https://issues.redhat.com/browse/AAP-57614

Summary

Forward-port of ansible/tower#7376 to devel (AAP 2.7).

  • Fix race condition where save_indirect_host_entries is never dispatched when artifacts_handler runs after handle_success_and_failure_notifications
  • Write event_queries_processed and installed_collections directly to the DB instead of using delay_update, so events_processed_hook sees the correct values regardless of execution order
  • Remove early dispatch from artifacts_handler; rely on the existing events_processed_hook which runs after events are in the DB

Test plan

  • Run integration tests in test_indirect_node_counting_external_queries.py via CI pipeline
  • Verify IndirectManagedNodeAudit records are created after job completion
  • Verify event_queries_processed transitions from False to True after processing

🤖 Generated with Claude Code

Classification

  • Bug, Docs Fix or other nominal change

Test Results


Note

Medium Risk
Adjusts job completion/indirect host processing coordination by changing when event_queries_processed (and related fields) are written, which could impact post-run hooks and task dispatch timing. Scope is small but touches job lifecycle behavior and DB update ordering.

Overview
Fixes a race in RunnerCallback.artifacts_handler where delayed field writes could cause events_processed_hook to miss that indirect host processing is required.

When ansible_data.json is present, the handler now writes event_queries_processed=False (and installed_collections when available) directly to the Job row instead of relying on delay_update, ensuring the flag is visible before wrap-up processing runs.

Written by Cursor Bugbot for commit 1a205af. This will update automatically on new commits. Configure here.

djulich and others added 4 commits March 22, 2026 21:22
…dler

The artifacts_handler and handle_success_and_failure_notifications can
run in either order after job completion. Since event_queries_processed
defaults to True on the Job model, when the notification handler runs
first it sees True (the default) and skips dispatching
save_indirect_host_entries. When artifacts_handler runs later and sets
event_queries_processed to False, no task is dispatched to process the
EventQuery records, leaving event_queries_processed stuck at False and
no IndirectManagedNodeAudit records created.

Fix by also dispatching save_indirect_host_entries from
artifacts_handler after EventQuery records are created. The task's
select_for_update lock prevents duplicate processing if both code
paths dispatch.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous commit dispatched save_indirect_host_entries from
artifacts_handler, but used delay_update to set event_queries_processed
to False. delay_update only queues the write for the final job status
save, so save_indirect_host_entries would read the default (True) from
the DB and bail out before processing.

Replace delay_update(event_queries_processed=False) with a direct
Job.objects.filter().update() call so the value is visible in the DB
before save_indirect_host_entries runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
save_indirect_host_entries calls fetch_job_event_query which reads
job.installed_collections from the DB. When dispatched from
artifacts_handler, installed_collections was still only in
delay_update (not yet flushed to DB), so the task found no matching
EventQuery records and created no IndirectManagedNodeAudit entries.

Write both event_queries_processed and installed_collections directly
to the DB before dispatching, so save_indirect_host_entries has all
the data it needs immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dispatching save_indirect_host_entries from artifacts_handler was
fundamentally flawed: it ran before job events were written to the DB
by the callback receiver, so the task found no events to process, set
event_queries_processed=True, and blocked all future processing.

Remove the dispatch and the now-unused import.  The existing
events_processed_hook (called from both the task runner after the
final save and the callback receiver after the wrapup event) handles
dispatching at the right time — after events are in the DB.

The direct DB write of event_queries_processed=False and
installed_collections (added in the previous commit) remains: it
ensures events_processed_hook sees the correct values regardless of
which call site runs first.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 22, 2026

📝 Walkthrough

Walkthrough

The RunnerCallback.artifacts_handler method is modified to change when certain database fields are persisted. event_queries_processed and installed_collections now use immediate direct database writes via Job.objects.filter().update() instead of being deferred until the final job status save.

Changes

Cohort / File(s) Summary
Callback Artifact Handler Persistence
awx/main/tasks/callback.py
Removed deferred delay_update() call for event_queries_processed. Added immediate direct database update using Job.objects.filter().update() to set event_queries_processed=False and installed_collections (when present). Retained deferred updates for installed_collections, ansible_version, and event_queries creation via existing delay_update() calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title mentions a 2.7 backport and references a specific issue (AAP-57614), but the PR objectives indicate this is a forward-port to devel from the 2.7 branch, creating a discrepancy. Clarify whether this is a backport or forward-port by updating the title to reflect the actual direction and target branch (e.g., 'AAP-57614 fix: forward-port artifacts_handler dispatch fix to devel').
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch AAP-57614-fix-artifacts-handler-dispatch-devel

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 and usage tips.

@djulich djulich changed the title AAP-57614 fix: forward-port artifacts_handler dispatch fix to devel [2.7 backport] AAP-57614 fix: dispatch save_indirect_host_entries from artifacts_handler Mar 22, 2026
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

db_updates = {'event_queries_processed': False}
if 'installed_collections' in query_file_contents:
db_updates['installed_collections'] = query_file_contents['installed_collections']
Job.objects.filter(id=self.instance.id).update(**db_updates)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Direct DB write skipped if earlier code raises exception

Medium Severity

The old code called delay_update(event_queries_processed=False) at the top of the if success: block, ensuring the flag was set even if later code raised an exception. The new direct DB write at lines 316–319 is placed at the end, after the EventQuery save loop. If an unhandled exception occurs in that loop (e.g., an IntegrityError from instance.save() that the except ValidationError doesn't catch), the direct DB write is skipped, event_queries_processed stays at the default True, and save_indirect_host_entries is never dispatched. The fallback task also won't recover this since it queries for event_queries_processed=False.

Fix in Cursor Fix in Web

@sonarqubecloud
Copy link
Copy Markdown

@djulich djulich marked this pull request as draft March 23, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant