Skip to content

Populate HostMetric.used_in_inventories with actual inventory counts#16355

Open
tll3r wants to merge 1 commit intoansible:develfrom
tll3r:fix/populate-used-in-inventories
Open

Populate HostMetric.used_in_inventories with actual inventory counts#16355
tll3r wants to merge 1 commit intoansible:develfrom
tll3r:fix/populate-used-in-inventories

Conversation

@tll3r
Copy link

@tll3r tll3r commented Mar 17, 2026

Summary

The used_in_inventories field on HostMetric was introduced in PR #13560 (Feb 2023) but the backend logic to populate it was never implemented, leaving the field permanently null since AAP 2.4. The UI column was subsequently removed in PR #13782 with the note "Revert this commit once the backend is ready."

This PR adds the missing backend:

  • HostMetricInventoryCountTask: counts distinct inventories per hostname by correlating Host.name with HostMetric.hostname via a single bulk UPDATE with a correlated subquery
  • update_host_metric_inventory_counts: scheduled task (dispatched every 4 hours, with an internal 7-day run-threshold guard matching the existing host_metric_summary_monthly pattern)
  • HOST_METRIC_INVENTORY_COUNTS_LAST_TS: persisted via the conf registry so the run-threshold survives restarts
  • awx-manage update_host_metric_inventory_counts: management command for on-demand execution
  • Functional tests: 6 tests covering zero hosts, single inventory, multiple inventories, mixed hosts, idempotency, and inventory membership changes

Related Issues

Test plan

  • awx-manage update_host_metric_inventory_counts populates the field correctly
  • Scheduled task runs on the configured interval
  • GET /api/v2/host_metrics/?order_by=-used_in_inventories returns correct non-null values
  • All existing host_metrics tests still pass
  • New functional tests pass: pytest awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py

Made with Cursor

Summary by CodeRabbit

  • New Features
    • Automatic periodic task (every 4 hours) to update host inventory membership counts.
    • System now records how many distinct inventories each host is used in.
    • Manual command to trigger inventory count updates on demand.
    • New configuration entries: last-run timestamp and an interval setting.
  • Tests
    • Added functional tests validating counts, idempotency, and dynamic updates.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ae6dd659-70bf-4042-80c6-cd80c58a7ae3

📥 Commits

Reviewing files that changed from the base of the PR and between 61c4740 and 1749ace.

📒 Files selected for processing (5)
  • awx/main/conf.py
  • awx/main/management/commands/update_host_metric_inventory_counts.py
  • awx/main/tasks/host_metrics.py
  • awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py
  • awx/settings/defaults.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • awx/settings/defaults.py
  • awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py
  • awx/main/management/commands/update_host_metric_inventory_counts.py

📝 Walkthrough

Walkthrough

Adds a periodic task, a management command, configuration entries, and tests to compute and store per-host distinct-inventory counts on HostMetric records and record the task's last-run timestamp and interval.

Changes

Cohort / File(s) Summary
Configuration & Scheduling
awx/main/conf.py, awx/settings/defaults.py
Added public config HOST_METRIC_INVENTORY_COUNTS_LAST_TS (DateTimeField, nullable, hidden) and constant HOST_METRIC_INVENTORY_COUNTS_INTERVAL = 1 (days); added awx.main.tasks.host_metrics.update_host_metric_inventory_counts to DISPATCHER_SCHEDULE (schedule: 14400).
Task Implementation
awx/main/tasks/host_metrics.py
Added periodic function update_host_metric_inventory_counts and HostMetricInventoryCountTask with static update_counts() that uses ORM Subquery/OuterRef/Coalesce to compute distinct inventory counts per hostname, update HostMetric.used_in_inventories, set last-run timestamp, and log results.
Management Command
awx/main/management/commands/update_host_metric_inventory_counts.py
New Command subclass that calls HostMetricInventoryCountTask.update_counts() and prints the number of updated HostMetric records.
Tests
awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py
New functional tests covering no-host cases, single/multiple inventories, mixed scenarios, idempotency, and dynamic inventory membership updates.

Sequence Diagram

sequenceDiagram
    participant Scheduler as Scheduler / Cron
    participant CLI as Management Command
    participant Task as HostMetricInventoryCountTask
    participant DB as Database (HostMetric, Host, Inventory)
    Scheduler->>CLI: Trigger scheduled task
    CLI->>Task: invoke update_counts()
    Task->>DB: SELECT COUNT(DISTINCT inventory_id) per hostname (Subquery/OuterRef)
    DB-->>Task: per-host inventory counts
    Task->>DB: UPDATE HostMetric.used_in_inventories (COALESCE counts, 0)
    Task->>DB: UPDATE config HOST_METRIC_INVENTORY_COUNTS_LAST_TS
    Task-->>CLI: return updated count
    CLI-->>Scheduler: output summary
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely describes the main change: populating the HostMetric.used_in_inventories column with actual inventory counts, which is the primary objective of this changeset.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@awx/main/tasks/host_metrics.py`:
- Around line 40-53: Wrap the threshold check and the call to
HostMetricInventoryCountTask.update_counts in a Postgres advisory lock so only
one worker can perform the check+update sequence: acquire the advisory lock at
the start of update_host_metric_inventory_counts (before calling
is_run_threshold_reached), re-check the threshold inside the lock, then call
HostMetricInventoryCountTask.update_counts and release the lock; use the
existing DB utilities or a pg_advisory_lock wrapper used elsewhere in the
project (or implement a short-timeout/non-blocking advisory lock) so concurrent
workers skip execution if they cannot obtain the lock.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: dcb3ca11-33ff-4e0a-8ac2-f0466d61cfd0

📥 Commits

Reviewing files that changed from the base of the PR and between 643a984 and 3139993.

📒 Files selected for processing (5)
  • awx/main/conf.py
  • awx/main/management/commands/update_host_metric_inventory_counts.py
  • awx/main/tasks/host_metrics.py
  • awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py
  • awx/settings/defaults.py

@tll3r tll3r force-pushed the fix/populate-used-in-inventories branch from 3139993 to 61c4740 Compare March 17, 2026 09:48
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@awx/main/tasks/host_metrics.py`:
- Around line 308-315: The current correlated-subquery approach in
inventory_count_subquery combined with
HostMetric.objects.update(used_in_inventories=...) forces a full-table rewrite;
instead compute the new counts in a single grouped query (use
Host.objects.values('name').annotate(new_cnt=Count('inventory_id',
distinct=True)) to get a mapping of hostname -> new_cnt), then query HostMetric
for hostnames where used_in_inventories != new_cnt
(HostMetric.objects.filter(hostname__in=..., used_in_inventories__ne=...)) and
apply updates only to those rows using bulk_update (or an efficient per-row
update loop) to set used_in_inventories to the computed value; finally set
settings.HOST_METRIC_INVENTORY_COUNTS_LAST_TS = now() only after performing the
selective updates.
- Around line 47-50: The current guard using is_run_threshold_reached with
getattr(settings, 'HOST_METRIC_INVENTORY_COUNTS_INTERVAL', 7) * 86400 makes the
HostMetric used_in_inventories refresh only once a week; update this to match
the dispatcher freshness (e.g., default to 4 hours) or remove the threshold
entirely. Modify the call in host_metrics.py that references
is_run_threshold_reached and the settings keys
HOST_METRIC_INVENTORY_COUNTS_LAST_TS and HOST_METRIC_INVENTORY_COUNTS_INTERVAL
so the default interval is 4*3600 (or delegate to the dispatcher interval
config) or eliminate the is_run_threshold_reached check so used_in_inventories
on HostMetric is recalculated every dispatcher run. Ensure any change keeps the
same settings names and semantics so tests and callers (HostMetric updates)
continue to work.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2875a846-0423-4009-afe9-4a4119d2399b

📥 Commits

Reviewing files that changed from the base of the PR and between 3139993 and 61c4740.

📒 Files selected for processing (5)
  • awx/main/conf.py
  • awx/main/management/commands/update_host_metric_inventory_counts.py
  • awx/main/tasks/host_metrics.py
  • awx/main/tests/functional/commands/test_update_host_metric_inventory_counts.py
  • awx/settings/defaults.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • awx/main/conf.py
  • awx/settings/defaults.py
  • awx/main/management/commands/update_host_metric_inventory_counts.py

Comment on lines +47 to +50
if is_run_threshold_reached(
getattr(settings, 'HOST_METRIC_INVENTORY_COUNTS_LAST_TS', None),
getattr(settings, 'HOST_METRIC_INVENTORY_COUNTS_INTERVAL', 7) * 86400,
):
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Defaulting this task to a 7-day threshold leaves the new field stale.

Line 49 throttles the only automatic refresh to once a week, so any HostMetric created or any inventory membership change after that run can leave used_in_inventories null/outdated for days even though the dispatcher wakes up every 4 hours. Please align this guard with the intended freshness of the field, or drop the extra threshold for this task.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@awx/main/tasks/host_metrics.py` around lines 47 - 50, The current guard using
is_run_threshold_reached with getattr(settings,
'HOST_METRIC_INVENTORY_COUNTS_INTERVAL', 7) * 86400 makes the HostMetric
used_in_inventories refresh only once a week; update this to match the
dispatcher freshness (e.g., default to 4 hours) or remove the threshold
entirely. Modify the call in host_metrics.py that references
is_run_threshold_reached and the settings keys
HOST_METRIC_INVENTORY_COUNTS_LAST_TS and HOST_METRIC_INVENTORY_COUNTS_INTERVAL
so the default interval is 4*3600 (or delegate to the dispatcher interval
config) or eliminate the is_run_threshold_reached check so used_in_inventories
on HostMetric is recalculated every dispatcher run. Ensure any change keeps the
same settings names and semantics so tests and callers (HostMetric updates)
continue to work.

The used_in_inventories field on HostMetric was introduced in PR ansible#13560
but the backend logic to populate it was never implemented, leaving the
field permanently null since AAP 2.4.

This adds:
- HostMetricInventoryCountTask: counts distinct inventories per hostname
  by correlating Host.name with HostMetric.hostname
- update_host_metric_inventory_counts: weekly scheduled task that invokes
  the count update (controlled via HOST_METRIC_INVENTORY_COUNTS_INTERVAL)
- DISPATCHER_SCHEDULE entry so the task runs automatically every 4 hours
  (with an internal 7-day threshold guard matching the existing pattern)
- HOST_METRIC_INVENTORY_COUNTS_LAST_TS registered in conf for persistence
- awx-manage update_host_metric_inventory_counts: management command for
  on-demand execution
- Functional tests covering zero, single, multiple inventories,
  mixed hosts, idempotency, and inventory membership changes

Resolves the incomplete feature tracked in AWX PRs ansible#13560, ansible#13782, ansible#13999.

Made-with: Cursor
@tll3r tll3r force-pushed the fix/populate-used-in-inventories branch from 61c4740 to 1749ace Compare March 17, 2026 10:02
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