Compare commits

..

1 Commits

Author SHA1 Message Date
Dirk Julich
fd1745a375 [AAP-78392] Optimize HostManager.active_count() with cache and functional index
active_count() runs a full sequential scan with LOWER()+DISTINCT on main_host for every license check. At customer scale this consumed 74.5 minutes of DB time over 4 hours (47K calls at 93ms avg).

Add a 60-second Redis-backed cache via the existing memoize decorator to reduce call volume by ~99.5%. Add a functional btree index on LOWER(name) to eliminate the sequential scan for the remaining calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-16 18:47:00 +02:00
8 changed files with 79 additions and 637 deletions

View File

@@ -1,471 +0,0 @@
{
"activity_stream_retrieve": "Retrieve an audit trail entry for tracking all changes within the system",
"ad_hoc_commands_activity_stream_list": "List activity stream of an ad hoc command",
"ad_hoc_commands_create": "Create an ad hoc command",
"ad_hoc_commands_destroy": "Delete an ad hoc command",
"ad_hoc_commands_events_list": "List events of an ad hoc command",
"ad_hoc_commands_list": "List ad hoc commands",
"ad_hoc_commands_notifications_list": "List notifications of an ad hoc command",
"ad_hoc_commands_retrieve": "Retrieve an ad hoc command",
"ad_hoc_commands_stdout_retrieve": "Retrieve a stdout output of an ad hoc command",
"analytics_adoption_rate_options_retrieve": "Retrieve single analytics adoption rate option",
"analytics_adoption_rate_retrieve": "Retrieve single analytics adoption rate",
"analytics_event_explorer_options_retrieve": "Retrieve single analytics event explorer option",
"analytics_event_explorer_retrieve": "Retrieve single analytics event explorer",
"analytics_host_explorer_options_retrieve": "Retrieve single analytics host explorer option",
"analytics_host_explorer_retrieve": "Retrieve single analytics host explorer",
"analytics_job_explorer_options_retrieve": "Retrieve single analytics job explorer option",
"analytics_job_explorer_retrieve": "Retrieve single analytics job explorer",
"analytics_probe_template_for_hosts_options_retrieve": "Retrieve single analytics probe template for hosts option",
"analytics_probe_template_for_hosts_retrieve": "Retrieve single analytics probe template for host",
"analytics_probe_templates_options_retrieve": "Retrieve single analytics probe templates option",
"analytics_probe_templates_retrieve": "Retrieve single analytics probe template",
"analytics_reports_retrieve": "Retrieve single analytics report",
"analytics_roi_templates_options_retrieve": "Retrieve single analytics roi templates option",
"analytics_roi_templates_retrieve": "Retrieve single analytics roi template",
"constructed_inventories_create": "Create a constructed inventory",
"constructed_inventories_destroy": "Delete a constructed inventory",
"constructed_inventories_partial_update": "Update a constructed inventory",
"constructed_inventories_retrieve": "Retrieve a constructed inventory",
"constructed_inventories_update": "Update a constructed inventory",
"credential_input_sources_create": "Create a credential input source",
"credential_input_sources_destroy": "Delete a credential input source",
"credential_input_sources_list": "List credential input sources",
"credential_input_sources_partial_update": "Update a credential input source",
"credential_input_sources_retrieve": "Retrieve a credential input source",
"credential_input_sources_update": "Update a credential input source",
"credential_types_credentials_create": "Create a credential of a credential type",
"credential_types_credentials_list": "List credentials of a credential type",
"credential_types_retrieve": "Retrieve a credential type",
"credential_types_test_retrieve": "Retrieve single test for a credential_type",
"credentials_destroy": "Delete a credential",
"credentials_input_sources_create": "Create new source for a credential",
"credentials_input_sources_list": "List all sources for a credential",
"credentials_object_roles_list": "List roles of a credential",
"credentials_owner_teams_list": "List all teams for a credential",
"credentials_owner_users_list": "List all users for a credential",
"credentials_partial_update": "Update a credential",
"credentials_retrieve": "Retrieve a credential",
"credentials_test_retrieve": "Retrieve a test external credential",
"credentials_update": "Update a credential",
"execution_environments_activity_stream_list": "List activity stream of an execution environment",
"execution_environments_copy_create": "Create new copy for an execution_environment",
"execution_environments_copy_retrieve": "Retrieve single copy for an execution_environment",
"execution_environments_retrieve": "Retrieve an execution environment",
"execution_environments_unified_job_templates_list": "List unified job templates using this execution environment",
"feature_flags_state_retrieve": "Retrieve single feature flags state",
"feature_flags_states_list": "List all feature flags states",
"feature_flags_states_retrieve": "Retrieve single feature flags state",
"groups_activity_stream_list": "List activity stream for a group",
"groups_ad_hoc_commands_create": "Create an ad hoc command for a group",
"groups_ad_hoc_commands_list": "List ad hoc commands for a group",
"groups_all_hosts_list": "List all hosts for a group",
"groups_children_create": "Create new child for a group",
"groups_children_list": "List all children for a group",
"groups_destroy": "Delete a group",
"groups_hosts_create": "Create a host of a group",
"groups_hosts_list": "List hosts of a group",
"groups_inventory_sources_list": "List inventory sources of a group",
"groups_job_events_list": "List job events for a group",
"groups_job_host_summaries_list": "List job host summaries for a group",
"groups_partial_update": "Update a group",
"groups_potential_children_list": "List all children for a group",
"groups_retrieve": "Retrieve a group",
"groups_update": "Update a group",
"groups_variable_data_partial_update": "Update a variable datum for a group",
"groups_variable_data_retrieve": "Retrieve a variable datum for a group",
"groups_variable_data_update": "Update a variable datum for a group",
"host_metric_summary_monthly_list": "List monthly summaries for host metrics",
"host_metrics_list": "List host metrics",
"host_metrics_retrieve": "Retrieve a host metric",
"hosts_activity_stream_list": "List activity stream for a host",
"hosts_ad_hoc_command_events_list": "List events of ad hoc command of a host",
"hosts_ad_hoc_commands_create": "Create an ad hoc command of a host",
"hosts_ad_hoc_commands_list": "List ad hoc commands of a host",
"hosts_all_groups_list": "List all groups for a host",
"hosts_create": "Create a host",
"hosts_groups_create": "Create the list of groups a host is directly a member of",
"hosts_groups_list": "List the list of groups a host is directly a member of",
"hosts_inventory_sources_list": "List inventory sources of a host",
"hosts_job_events_list": "List job events of a host",
"hosts_job_host_summaries_list": "List job summaries of a host",
"hosts_partial_update": "Update a host",
"hosts_retrieve": "Retrieve a host",
"hosts_smart_inventories_list": "List all inventories for a host",
"hosts_update": "Update a host",
"hosts_variable_data_partial_update": "Update a variable datum for a host",
"hosts_variable_data_update": "Update a variable datum for a host",
"instance_groups_destroy": "Delete an instance group",
"instance_groups_instances_create": "Create an instance of an instance group",
"instance_groups_instances_list": "List instance of an instance group",
"instance_groups_jobs_list": "List jobs of an instance group",
"instance_groups_object_roles_list": "List all roles for an instance_group",
"instance_groups_partial_update": "Update an instance group",
"instance_groups_retrieve": "Retrieve an instance group",
"instance_groups_update": "Update an instance group",
"instances_instance_groups_create": "Create an instance group of an instance",
"instances_instance_groups_list": "List instance groups of an instance",
"instances_jobs_list": "List jobs executed on an instance",
"instances_list": "List instances",
"instances_partial_update": "Update an instance",
"instances_peers_list": "List all peers for an instance",
"instances_retrieve": "Retrieve an instance",
"instances_update": "Update an instance",
"inventories_access_list_list": "List users who can access the inventory",
"inventories_ad_hoc_commands_create": "Create an ad hoc command for an inventory",
"inventories_ad_hoc_commands_list": "List ad hoc command for an inventory",
"inventories_copy_create": "Create a copy of an inventory",
"inventories_copy_retrieve": "Retrieve a copy of an inventory",
"inventories_create": "Create an inventory",
"inventories_destroy": "Delete an inventory",
"inventories_groups_create": "Create a group of an inventory",
"inventories_groups_list": "List groups of an inventory",
"inventories_hosts_create": "Create a host of an inventory",
"inventories_hosts_list": "List hosts of an inventory",
"inventories_instance_groups_create": "Create an instance group of an inventory",
"inventories_instance_groups_list": "List instance groups of an inventory",
"inventories_inventory_sources_create": "Create an inventory source",
"inventories_inventory_sources_list": "List inventory sources",
"inventories_job_templates_list": "List job templates using an inventory",
"inventories_labels_list": "List labels of an inventory",
"inventories_object_roles_list": "List roles of an inventory",
"inventories_partial_update": "Update an inventory",
"inventories_retrieve": "Retrieve an inventory",
"inventories_update": "Update an inventory",
"inventories_update_inventory_sources_retrieve": "Retrieve single source for an inventory",
"inventories_variable_data_partial_update": "Partially update existing datum for an inventory",
"inventories_variable_data_retrieve": "Retrieve single datum for an inventory",
"inventories_variable_data_update": "Update existing datum for an inventory",
"inventory_sources_activity_stream_list": "List activity stream of an inventory source",
"inventory_sources_create": "Create an inventory source",
"inventory_sources_credentials_create": "Create a credential of an inventory source",
"inventory_sources_credentials_list": "List credentials of an inventory source",
"inventory_sources_destroy": "Delete an inventory source",
"inventory_sources_groups_destroy": "Delete a group of an inventory source",
"inventory_sources_groups_list": "List groups of an inventory source",
"inventory_sources_hosts_destroy": "Delete a host of an inventory source",
"inventory_sources_hosts_list": "List hosts of an inventory source",
"inventory_sources_inventory_updates_list": "List inventory updates of an inventory source",
"inventory_sources_list": "List inventory sources",
"inventory_sources_notification_templates_error_list": "List notification templates triggered on inventory source update error",
"inventory_sources_notification_templates_started_list": "List notification templates triggered on inventory source update start",
"inventory_sources_notification_templates_success_list": "List notification templates triggered on inventory source update success",
"inventory_sources_partial_update": "Update an inventory source",
"inventory_sources_retrieve": "Retrieve an inventory source",
"inventory_sources_schedules_create": "Create a schedule of an inventory source",
"inventory_sources_schedules_list": "List schedules of an inventory source",
"inventory_sources_update": "Update an inventory source",
"inventory_sources_update_retrieve": "Retrieve an update for an inventory source",
"inventory_updates_cancel_create": "Create a cancel for an inventory update",
"inventory_updates_cancel_retrieve": "Retrieve a cancel for an inventory update",
"inventory_updates_credentials_list": "List credentials of an inventory update",
"inventory_updates_destroy": "Delete an inventory update",
"inventory_updates_events_list": "List events of an inventory update",
"inventory_updates_list": "List inventory updates",
"inventory_updates_notifications_list": "List notifications of an inventory update",
"inventory_updates_retrieve": "Retrieve an inventory update",
"inventory_updates_stdout_retrieve": "Retrieve a stdout output of an inventory update",
"job_events_children_list": "List child events of a job event",
"job_events_retrieve": "Retrieve a job event detail",
"job_host_summaries_retrieve": "Retrieve a job host summary detail",
"job_templates_access_list_list": "List users who can access a job template",
"job_templates_activity_stream_list": "List activity stream of a job template",
"job_templates_copy_create": "Create a copy a job template",
"job_templates_copy_retrieve": "Retrieve a copy a job template",
"job_templates_create": "Create a job template",
"job_templates_credentials_create": "Create a credential of a job template",
"job_templates_credentials_list": "List credentials of a job template",
"job_templates_destroy": "Delete a job template",
"job_templates_instance_groups_create": "Create an instance group of a job template",
"job_templates_instance_groups_list": "List instance groups of a job template",
"job_templates_jobs_list": "List jobs of a job template",
"job_templates_labels_list": "List labels of a job template",
"job_templates_launch_retrieve": "Retrieve single launch for a job_template",
"job_templates_notification_templates_error_create": "Create a notification templates triggered on job error",
"job_templates_notification_templates_error_list": "List notification templates triggered on job error",
"job_templates_notification_templates_started_create": "Create a notification templates triggered on job start",
"job_templates_notification_templates_started_list": "List notification templates triggered on job start",
"job_templates_notification_templates_success_create": "Create a notification templates triggered on job success",
"job_templates_notification_templates_success_list": "List notification templates triggered on job success",
"job_templates_object_roles_list": "List roles of a job template",
"job_templates_partial_update": "Update a job template",
"job_templates_retrieve": "Retrieve a job template",
"job_templates_schedules_create": "Create a schedule of a job template",
"job_templates_schedules_list": "List schedules of a job template",
"job_templates_slice_workflow_jobs_create": "Create new job for a job_template",
"job_templates_slice_workflow_jobs_list": "List all jobs for a job_template",
"job_templates_update": "Update a job template",
"jobs_activity_stream_list": "List activity stream of a job",
"jobs_cancel_retrieve": "Retrieve a cancel for a job",
"jobs_create_schedule_retrieve": "Retrieve single schedule for a job",
"jobs_credentials_list": "List credentials of a job",
"jobs_destroy": "Delete a job",
"jobs_job_events_list": "List job events of a job",
"jobs_job_host_summaries_list": "List job host summaries of a job",
"jobs_labels_list": "List labels of a job",
"jobs_notifications_list": "List notifications of a job",
"jobs_relaunch_retrieve": "Retrieve single relaunch for a job",
"jobs_retrieve": "Retrieve a job",
"labels_create": "Create a label",
"labels_list": "List labels",
"labels_partial_update": "Update a label",
"labels_retrieve": "Retrieve a label",
"labels_update": "Update a label",
"me_list": "List current authenticated user",
"notification_templates_copy_create": "Create a copy a notification template",
"notification_templates_copy_retrieve": "Retrieve a copy a notification template",
"notification_templates_notifications_list": "List notifications of a notification template",
"notification_templates_retrieve": "Retrieve a notification template",
"notifications_list": "List notifications",
"notifications_retrieve": "Retrieve a notification",
"organizations_access_list_list": "List users who can access the organization",
"organizations_activity_stream_list": "List activity stream for an organization",
"organizations_admins_create": "Create new admin for an organization",
"organizations_admins_list": "List all admins for an organization",
"organizations_create": "Create an organization",
"organizations_credentials_create": "Create a credential of an organization",
"organizations_credentials_list": "List credentials of an organization",
"organizations_destroy": "Delete an organization",
"organizations_execution_environments_create": "Create an execution environment of an organization",
"organizations_execution_environments_list": "List execution environments of an organization",
"organizations_galaxy_credentials_create": "Create new credential for an organization",
"organizations_galaxy_credentials_list": "List all credentials for an organization",
"organizations_instance_groups_create": "Create an instance group of an organization",
"organizations_instance_groups_list": "List instance groups of an organization",
"organizations_inventories_list": "List inventories of an organization",
"organizations_job_templates_create": "Create a job template of an organization",
"organizations_job_templates_list": "List job templates of an organization",
"organizations_notification_templates_approvals_create": "Create new approval for an organization",
"organizations_notification_templates_approvals_list": "List all approvals for an organization",
"organizations_notification_templates_create": "Create a notification template of an organization",
"organizations_notification_templates_error_create": "Create new error for an organization",
"organizations_notification_templates_error_list": "List all error for an organization",
"organizations_notification_templates_list": "List notification templates of an organization",
"organizations_notification_templates_started_create": "Create new started for an organization",
"organizations_notification_templates_started_list": "List all started for an organization",
"organizations_notification_templates_success_create": "Create new success for an organization",
"organizations_notification_templates_success_list": "List all success for an organization",
"organizations_object_roles_list": "List roles of an organization",
"organizations_partial_update": "Update an organization",
"organizations_projects_create": "Create a project of an organization",
"organizations_projects_list": "List projects of an organization",
"organizations_retrieve": "Retrieve an organization",
"organizations_retrieve_2": "Retrieve an organization",
"organizations_teams_create": "Create a team of an organization",
"organizations_teams_list": "List teams of an organization",
"organizations_update": "Update an organization",
"organizations_users_create": "Create a user of an organization",
"organizations_users_list": "List users of an organization",
"organizations_workflow_job_templates_create": "Create a workflow job template of an organization",
"organizations_workflow_job_templates_list": "List workflow job templates of an organization",
"project_updates_cancel_create": "Create new cancel for a project_update",
"project_updates_cancel_retrieve": "Retrieve single cancel for a project_update",
"project_updates_destroy": "Delete a project update",
"project_updates_events_list": "List all events for a project_update",
"project_updates_list": "List project updates",
"project_updates_notifications_list": "List notifications of a project update",
"project_updates_retrieve": "Retrieve a project update",
"project_updates_scm_inventory_updates_list": "List all updates for a project_update",
"project_updates_stdout_retrieve": "Retrieve single stdout for a project_update",
"projects_access_list_list": "List users who can access the project",
"projects_activity_stream_list": "List activity stream for a project",
"projects_copy_create": "Create a copy of a project",
"projects_copy_retrieve": "Retrieve a copy of a project",
"projects_create": "Create a project",
"projects_destroy": "Delete a project",
"projects_inventories_retrieve": "Retrieve an inventory from a project",
"projects_notification_templates_error_create": "Create a notification template for project error events",
"projects_notification_templates_error_list": "List notification templates for project error events",
"projects_notification_templates_started_create": "Create a notification template for project started events",
"projects_notification_templates_started_list": "List notification templates for project started events",
"projects_notification_templates_success_create": "Create a notification template for project success events",
"projects_notification_templates_success_list": "List notification templates for project success events",
"projects_object_roles_list": "List roles of a project",
"projects_partial_update": "Update a project",
"projects_playbooks_retrieve": "Retrieve single playbook for a project",
"projects_project_updates_list": "List project updates of a project",
"projects_retrieve": "Retrieve a project",
"projects_schedules_create": "Create a schedule of a project",
"projects_schedules_list": "List schedules of a project",
"projects_scm_inventory_sources_list": "List all sources for a project",
"projects_teams_list": "List teams with access to a project",
"projects_update": "Update a project",
"projects_update_retrieve": "Retrieve single update for a project",
"receptor_addresses_list": "List receptor addresses",
"receptor_addresses_retrieve": "Retrieve a receptor address",
"role_definitions_create": "Create a RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_destroy": "Delete a RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_list": "List RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_partial_update": "Update a RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_retrieve": "Retrieve a RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_team_assignments_list": "List all assignments for a role_definition",
"role_definitions_update": "Update a RBAC roles defining permissions that can be managed and assigned to users and teams",
"role_definitions_user_assignments_list": "List all assignments for a role_definition",
"role_metadata_retrieve": "Retrieve single role metadatum",
"role_team_access_list": "List all role team access",
"role_team_access_list_2": "List all role team access",
"role_team_assignments_create": "Create a RBAC role grants assigning permissions to team for specific resources",
"role_team_assignments_destroy": "Delete a RBAC role grants assigning permissions to team for specific resources",
"role_team_assignments_list": "List RBAC role grants assigning permissions to teams for specific resources",
"role_team_assignments_retrieve": "Retrieve a RBAC role grants assigning permissions to team for specific resources",
"role_user_access_list": "List all role user access",
"role_user_access_list_2": "List all role user access",
"role_user_assignments_create": "Create a RBAC role grants assigning permissions to user for specific resources",
"role_user_assignments_destroy": "Delete a RBAC role grants assigning permissions to user for specific resources",
"role_user_assignments_list": "List RBAC role grants assigning permissions to users for specific resources",
"role_user_assignments_retrieve": "Retrieve a RBAC role grants assigning permissions to user for specific resources",
"roles_list": "List roles",
"roles_retrieve": "Retrieve a role",
"roles_teams_list": "List teams with a role",
"roles_users_list": "List users with a role",
"schedules_create": "Create a schedule",
"schedules_credentials_create": "Create a credential of a schedule",
"schedules_credentials_list": "List credentials of a schedule",
"schedules_destroy": "Delete a schedule",
"schedules_instance_groups_create": "Create an instance group of a schedule",
"schedules_instance_groups_list": "List instance groups of a schedule",
"schedules_jobs_list": "List jobs created by a schedule",
"schedules_labels_list": "List labels of a schedule",
"schedules_list": "List schedules",
"schedules_partial_update": "Update a schedule",
"schedules_retrieve": "Retrieve a schedule",
"schedules_update": "Update a schedule",
"service_index_metadata_retrieve": "Retrieve single service index metadatum",
"service_index_resource_types_list": "List all service index resource types",
"service_index_resource_types_manifest_retrieve": "Retrieve single manifest for a resource-type",
"service_index_resource_types_retrieve": "Retrieve single service index resource type",
"service_index_resources_create": "Create new service index resource",
"service_index_resources_destroy": "Delete existing service index resource",
"service_index_resources_list": "List all service index resources",
"service_index_resources_partial_update": "Partially update existing service index resource",
"service_index_resources_retrieve": "Retrieve single service index resource",
"service_index_resources_update": "Update existing service index resource",
"service_index_retrieve": "Retrieve single service index",
"service_index_role_permissions_list": "List all service index role permissions",
"service_index_role_team_assignments_assign_create": "Create new service index role team assignments assign",
"service_index_role_team_assignments_list": "List all service index role team assignments",
"service_index_role_team_assignments_unassign_create": "Create new service index role team assignments unassign",
"service_index_role_types_list": "List all service index role types",
"service_index_role_user_assignments_assign_create": "Create new service index role user assignments assign",
"service_index_role_user_assignments_list": "List all service index role user assignments",
"service_index_role_user_assignments_unassign_create": "Create new service index role user assignments unassign",
"settings_destroy": "Delete existing setting",
"settings_logging_test_create": "Create new settings logging test",
"settings_retrieve": "Retrieve single setting",
"settings_update": "Update existing setting",
"system_job_templates_jobs_list": "List system jobs of a system job template",
"system_job_templates_notification_templates_error_create": "Create a notification templates triggered on system job error",
"system_job_templates_notification_templates_error_list": "List notification templates triggered on system job error",
"system_job_templates_notification_templates_started_create": "Create a notification templates triggered on system job start",
"system_job_templates_notification_templates_started_list": "List notification templates triggered on system job start",
"system_job_templates_notification_templates_success_create": "Create a notification templates triggered on system job success",
"system_job_templates_notification_templates_success_list": "List notification templates triggered on system job success",
"system_job_templates_retrieve": "Retrieve a system job template",
"system_job_templates_schedules_create": "Create a schedule of a system job template",
"system_job_templates_schedules_list": "List schedules of a system job template",
"system_jobs_cancel_create": "Create a cancel for a system job",
"system_jobs_cancel_retrieve": "Retrieve a cancel for a system job",
"system_jobs_destroy": "Delete a system job",
"system_jobs_events_list": "List events of a system job",
"system_jobs_notifications_list": "List notifications of a system job",
"system_jobs_retrieve": "Retrieve a system job",
"teams_access_list_list": "List users who can access the team",
"teams_activity_stream_list": "List activity stream for a team",
"teams_create": "Create a team",
"teams_credentials_create": "Create a credentials owned by a team",
"teams_credentials_list": "List credentials owned by a team",
"teams_destroy": "Delete a team",
"teams_list": "List teams",
"teams_object_roles_list": "List object roles of a team",
"teams_partial_update": "Update a team",
"teams_projects_list": "List projects accessible to a team",
"teams_retrieve": "Retrieve a team",
"teams_roles_list": "List roles of a team",
"teams_update": "Update a team",
"teams_users_create": "Create a user of a team",
"teams_users_list": "List users of a team",
"unified_job_templates_list": "List unified job templates",
"unified_jobs_list": "List unified jobs",
"users_access_list_list": "List users who can access the user",
"users_activity_stream_list": "List activity stream for a user",
"users_admin_of_organizations_retrieve": "Retrieve single organization for an user",
"users_create": "Create a user",
"users_credentials_create": "Create a credentials owned by a user",
"users_credentials_list": "List credentials owned by a user",
"users_destroy": "Delete a user",
"users_list": "List users",
"users_organizations_retrieve": "Retrieve an organization of a user",
"users_partial_update": "Update a user",
"users_projects_list": "List projects accessible to a user",
"users_retrieve": "Retrieve a user",
"users_roles_list": "List roles of a user",
"users_teams_list": "List teams of a user",
"users_update": "Update a user",
"workflow_approval_templates_approvals_list": "List all approvals for a workflow_approval_template",
"workflow_approval_templates_destroy": "Delete a workflow approval template detail",
"workflow_approval_templates_partial_update": "Update a workflow approval template detail",
"workflow_approval_templates_retrieve": "Retrieve a workflow approval template detail",
"workflow_approval_templates_update": "Update a workflow approval template detail",
"workflow_approvals_approve_retrieve": "Retrieve single approve for a workflow_approval",
"workflow_approvals_deny_retrieve": "Retrieve single deny for a workflow_approval",
"workflow_approvals_destroy": "Delete a workflow approval",
"workflow_approvals_retrieve": "Retrieve a workflow approval",
"workflow_job_nodes_always_nodes_list": "List always nodes of a workflow job node",
"workflow_job_nodes_credentials_list": "List credentials of a workflow job node",
"workflow_job_nodes_failure_nodes_list": "List failure nodes of a workflow job node",
"workflow_job_nodes_instance_groups_create": "Create an instance group of a workflow job node",
"workflow_job_nodes_instance_groups_list": "List instance groups of a workflow job node",
"workflow_job_nodes_labels_list": "List labels of a workflow job node",
"workflow_job_nodes_list": "List workflow job nodes",
"workflow_job_nodes_retrieve": "Retrieve a workflow job node",
"workflow_job_nodes_success_nodes_list": "List success nodes of a workflow job node",
"workflow_job_template_nodes_always_nodes_create": "Create new node for a workflow_job_template_node",
"workflow_job_template_nodes_always_nodes_list": "List all nodes for a workflow_job_template_node",
"workflow_job_template_nodes_create": "Create a workflow job template node",
"workflow_job_template_nodes_create_approval_template_retrieve": "Retrieve single template for a workflow_job_template_node",
"workflow_job_template_nodes_credentials_create": "Create a credential of a workflow job template node",
"workflow_job_template_nodes_credentials_list": "List credentials of a workflow job template node",
"workflow_job_template_nodes_destroy": "Delete a workflow job template node",
"workflow_job_template_nodes_failure_nodes_create": "Create new node for a workflow_job_template_node",
"workflow_job_template_nodes_failure_nodes_list": "List all nodes for a workflow_job_template_node",
"workflow_job_template_nodes_instance_groups_create": "Create an instance group of a workflow job template node",
"workflow_job_template_nodes_instance_groups_list": "List instance groups of a workflow job template node",
"workflow_job_template_nodes_labels_list": "List labels of a workflow job template node",
"workflow_job_template_nodes_list": "List workflow job template nodes",
"workflow_job_template_nodes_partial_update": "Update a workflow job template node",
"workflow_job_template_nodes_retrieve": "Retrieve a workflow job template node",
"workflow_job_template_nodes_success_nodes_create": "Create new node for a workflow_job_template_node",
"workflow_job_template_nodes_success_nodes_list": "List all nodes for a workflow_job_template_node",
"workflow_job_template_nodes_update": "Update a workflow job template node",
"workflow_job_templates_access_list_list": "List users who can access a workflow job template",
"workflow_job_templates_activity_stream_list": "List activity stream of a workflow job template",
"workflow_job_templates_copy_create": "Create a copy a workflow job template",
"workflow_job_templates_create": "Create a workflow job template",
"workflow_job_templates_destroy": "Delete a workflow job template",
"workflow_job_templates_labels_list": "List labels of a workflow job template",
"workflow_job_templates_launch_retrieve": "Retrieve a launch a workflow job from a workflow job template",
"workflow_job_templates_notification_templates_approvals_create": "Create a notification templates triggered on workflow approval",
"workflow_job_templates_notification_templates_approvals_list": "List notification templates triggered on workflow approval",
"workflow_job_templates_notification_templates_error_create": "Create a notification templates triggered on workflow job error",
"workflow_job_templates_notification_templates_error_list": "List notification templates triggered on workflow job error",
"workflow_job_templates_notification_templates_started_create": "Create a notification templates triggered on workflow job start",
"workflow_job_templates_notification_templates_started_list": "List notification templates triggered on workflow job start",
"workflow_job_templates_notification_templates_success_create": "Create a notification templates triggered on workflow job success",
"workflow_job_templates_notification_templates_success_list": "List notification templates triggered on workflow job success",
"workflow_job_templates_object_roles_list": "List roles of a workflow job template",
"workflow_job_templates_partial_update": "Update a workflow job template",
"workflow_job_templates_retrieve": "Retrieve a workflow job template",
"workflow_job_templates_schedules_create": "Create a schedule of a workflow job template",
"workflow_job_templates_schedules_list": "List schedules of a workflow job template",
"workflow_job_templates_update": "Update a workflow job template",
"workflow_job_templates_workflow_jobs_list": "List workflow jobs of a workflow job template",
"workflow_job_templates_workflow_nodes_create": "Create new node for a workflow_job_template",
"workflow_job_templates_workflow_nodes_list": "List all nodes for a workflow_job_template",
"workflow_jobs_activity_stream_list": "List activity stream of a workflow job",
"workflow_jobs_cancel_retrieve": "Retrieve a cancel for a workflow job",
"workflow_jobs_destroy": "Delete a workflow job",
"workflow_jobs_labels_list": "List labels of a workflow job",
"workflow_jobs_notifications_list": "List notifications of a workflow job",
"workflow_jobs_retrieve": "Retrieve a workflow job",
"workflow_jobs_workflow_nodes_list": "List workflow nodes of a workflow job"
}

View File

@@ -1,5 +1,3 @@
import json
import os
import warnings
from rest_framework.permissions import IsAuthenticated
@@ -55,37 +53,6 @@ def filter_credential_type_schema(
return result
def inject_ai_descriptions(
result,
generator, # NOSONAR
request, # NOSONAR
public, # NOSONAR
):
"""
Inject x-ai-description into operations from the overlay file.
Many endpoints have human-readable AI descriptions that were added
downstream but not backported as @extend_schema_if_available decorators.
This hook merges them from a JSON file keyed by operationId.
"""
overlay_path = os.path.join(os.path.dirname(__file__), 'openapi_ai_descriptions.json')
try:
with open(overlay_path) as f:
descriptions = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
return result
for path_item in result.get('paths', {}).values():
for operation in path_item.values():
if not isinstance(operation, dict):
continue
op_id = operation.get('operationId')
if op_id and op_id in descriptions and 'x-ai-description' not in operation:
operation['x-ai-description'] = descriptions[op_id]
return result
class CustomAutoSchema(AutoSchema):
"""Custom AutoSchema to add swagger_topic to tags and handle deprecated endpoints."""

View File

@@ -10,6 +10,7 @@ from django.db.models.functions import Lower
from ansible_base.lib.utils.db import advisory_lock
from awx.main.utils.common import memoize
from awx.main.utils.filters import SmartFilter
from awx.main.constants import RECEPTOR_PENDING
@@ -85,6 +86,7 @@ class HostLatestSummaryQuerySet(models.QuerySet):
class HostManager(models.Manager.from_queryset(HostLatestSummaryQuerySet)):
"""Custom manager class for Hosts model."""
@memoize(ttl=60, cache_key='host_active_count')
def active_count(self):
"""Return count of active, unique hosts for licensing.
Construction of query involves:

View File

@@ -0,0 +1,19 @@
from django.db import migrations, models
from django.db.models.functions import Lower
class Migration(migrations.Migration):
dependencies = [
('main', '0205_add_ordering_to_instancegroup_and_workflow_nodes'),
]
operations = [
migrations.AddIndex(
model_name='host',
index=models.Index(
Lower('name'),
name='main_host_name_lower_idx',
),
),
]

View File

@@ -19,6 +19,7 @@ from django.core.exceptions import ValidationError
from django.urls import resolve
from django.utils.timezone import now
from django.db.models import Q, Subquery, OuterRef
from django.db.models.functions import Lower
# REST Framework
from rest_framework.exceptions import ParseError
@@ -523,6 +524,9 @@ class Host(CommonModelNameNotUnique, RelatedJobsMixin):
app_label = 'main'
unique_together = (("name", "inventory"),) # FIXME: Add ('instance_id', 'inventory') after migration.
ordering = ('name',)
indexes = [
models.Index(Lower('name'), name='main_host_name_lower_idx'),
]
inventory = models.ForeignKey(
'Inventory',

View File

@@ -92,6 +92,22 @@ class TestInventoryScript:
@pytest.mark.django_db
class TestActiveCount:
@pytest.fixture(autouse=True)
def _bypass_active_count_cache(self):
from django.core.cache import cache
cache.delete('host_active_count')
original_set = cache.set
def skip_host_cache(key, *args, **kwargs):
if key == 'host_active_count':
return
return original_set(key, *args, **kwargs)
with mock.patch.object(cache, 'set', side_effect=skip_host_cache):
yield
cache.delete('host_active_count')
def test_host_active_count(self, organization):
inv1 = Inventory.objects.create(name='inv1', organization=organization)
inv2 = Inventory.objects.create(name='inv2', organization=organization)
@@ -141,6 +157,41 @@ class TestActiveCount:
assert Host.objects.active_count() == 2
@pytest.mark.django_db
class TestActiveCountCache:
@pytest.fixture(autouse=True)
def _clear_active_count_cache(self):
from awx.main.utils.common import memoize_delete
memoize_delete('host_active_count')
yield
memoize_delete('host_active_count')
def test_active_count_cache(self, organization):
inv = Inventory.objects.create(name='inv1', organization=organization)
inv.hosts.create(name='host1')
assert Host.objects.active_count() == 1
inv.hosts.create(name='host2')
assert Host.objects.active_count() == 1 # still cached
from awx.main.utils.common import memoize_delete
memoize_delete('host_active_count')
assert Host.objects.active_count() == 2
def test_active_count_cache_after_delete(self, organization):
inv = Inventory.objects.create(name='inv1', organization=organization)
h = inv.hosts.create(name='host1')
assert Host.objects.active_count() == 1
h.delete()
from awx.main.utils.common import memoize_delete
memoize_delete('host_active_count')
assert Host.objects.active_count() == 0
@pytest.mark.django_db
class TestSCMUpdateFeatures:
def test_source_location(self, scm_inventory_source):

View File

@@ -1,7 +1,6 @@
import copy
import json
import warnings
from unittest.mock import Mock, mock_open, patch
from unittest.mock import Mock, patch
from rest_framework.permissions import IsAuthenticated
@@ -11,7 +10,6 @@ from awx.api.schema import (
AuthenticatedSpectacularSwaggerView,
AuthenticatedSpectacularRedocView,
filter_credential_type_schema,
inject_ai_descriptions,
)
@@ -424,128 +422,3 @@ class TestFilterCredentialTypeSchema:
# PATCH schema: includes None (optional field)
assert result['components']['schemas']['PatchedCredentialTypeRequest']['properties']['kind']['enum'] == ['cloud', 'net', None]
class TestInjectAiDescriptions:
"""Unit tests for inject_ai_descriptions postprocessing hook."""
def _make_result(self, operations):
"""Build a minimal OpenAPI result dict from a list of (path, method, operationId, existing_desc) tuples."""
paths = {}
for path, method, op_id, desc in operations:
paths.setdefault(path, {})[method] = {'operationId': op_id}
if desc:
paths[path][method]['x-ai-description'] = desc
return {'paths': paths}
def test_injects_missing_descriptions(self):
"""Test that descriptions are injected for operations without x-ai-description."""
overlay = {'op_list': 'List items', 'op_create': 'Create an item'}
result = self._make_result(
[
('/api/v2/items/', 'get', 'op_list', None),
('/api/v2/items/', 'post', 'op_create', None),
]
)
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
returned = inject_ai_descriptions(result, None, None, None)
assert result['paths']['/api/v2/items/']['get']['x-ai-description'] == 'List items'
assert result['paths']['/api/v2/items/']['post']['x-ai-description'] == 'Create an item'
assert returned is result
def test_does_not_overwrite_existing_descriptions(self):
"""Test that existing x-ai-description from decorators is preserved."""
overlay = {'op_list': 'Overlay description'}
result = self._make_result(
[
('/api/v2/items/', 'get', 'op_list', 'Decorator description'),
]
)
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
inject_ai_descriptions(result, None, None, None)
assert result['paths']['/api/v2/items/']['get']['x-ai-description'] == 'Decorator description'
def test_skips_operations_not_in_overlay(self):
"""Test that operations without a matching operationId in the overlay are unchanged."""
overlay = {'op_other': 'Other description'}
result = self._make_result(
[
('/api/v2/items/', 'get', 'op_list', None),
]
)
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
inject_ai_descriptions(result, None, None, None)
assert 'x-ai-description' not in result['paths']['/api/v2/items/']['get']
def test_handles_missing_overlay_file(self):
"""Test graceful handling when the overlay file doesn't exist."""
result = self._make_result(
[
('/api/v2/items/', 'get', 'op_list', None),
]
)
original = copy.deepcopy(result)
with patch('builtins.open', side_effect=FileNotFoundError):
returned = inject_ai_descriptions(result, None, None, None)
assert result == original
assert returned is result
def test_handles_invalid_json(self):
"""Test graceful handling when the overlay file contains invalid JSON."""
result = self._make_result(
[
('/api/v2/items/', 'get', 'op_list', None),
]
)
original = copy.deepcopy(result)
with patch('builtins.open', mock_open(read_data='not valid json')):
returned = inject_ai_descriptions(result, None, None, None)
assert result == original
assert returned is result
def test_handles_empty_result(self):
"""Test graceful handling when result has no paths."""
result = {}
overlay = {'op_list': 'List items'}
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
returned = inject_ai_descriptions(result, None, None, None)
assert returned is result
def test_skips_non_dict_path_items(self):
"""Test that non-dict values in path items (e.g. parameters list) are skipped."""
overlay = {'op_list': 'List items'}
result = {
'paths': {
'/api/v2/items/': {
'parameters': [{'name': 'id', 'in': 'path'}],
'get': {'operationId': 'op_list'},
}
}
}
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
inject_ai_descriptions(result, None, None, None)
assert result['paths']['/api/v2/items/']['get']['x-ai-description'] == 'List items'
def test_handles_operation_without_operation_id(self):
"""Test that operations without operationId are skipped."""
overlay = {'op_list': 'List items'}
result = {'paths': {'/api/v2/items/': {'get': {'summary': 'List'}}}}
with patch('builtins.open', mock_open(read_data=json.dumps(overlay))):
inject_ai_descriptions(result, None, None, None)
assert 'x-ai-description' not in result['paths']['/api/v2/items/']['get']

View File

@@ -1038,11 +1038,8 @@ SPECTACULAR_SETTINGS = {
# Use our custom schema class that handles swagger_topic and deprecated views
'DEFAULT_SCHEMA_CLASS': 'awx.api.schema.CustomAutoSchema',
'COMPONENT_SPLIT_REQUEST': True,
# Postprocessing hooks for OpenAPI schema generation
'POSTPROCESSING_HOOKS': [
'awx.api.schema.filter_credential_type_schema',
'awx.api.schema.inject_ai_descriptions',
],
# Postprocessing hook to filter CredentialType enum values
'POSTPROCESSING_HOOKS': ['awx.api.schema.filter_credential_type_schema'],
'SWAGGER_UI_SETTINGS': {
'deepLinking': True,
'persistAuthorization': True,