From 485dd1721f4daaf511275839f04f3998e913f5cd Mon Sep 17 00:00:00 2001 From: Justin Sherrill Date: Thu, 29 Jun 2017 12:04:14 -0400 Subject: [PATCH] Fixes #20167 - speed up errata api --- .../katello/api/v2/errata_controller.rb | 5 +++-- app/models/katello/erratum.rb | 20 ++++++++++++++----- app/models/katello/host/content_facet.rb | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/app/controllers/katello/api/v2/errata_controller.rb b/app/controllers/katello/api/v2/errata_controller.rb index e960abd1e94..f51563e94a8 100644 --- a/app/controllers/katello/api/v2/errata_controller.rb +++ b/app/controllers/katello/api/v2/errata_controller.rb @@ -14,6 +14,7 @@ class Api::V2::ErrataController < Api::V2::ApiController param :errata_restrict_installable, :bool, :desc => N_("show only errata with one or more installable hosts") param_group :search, Api::V2::ApiController def index + params[:errata_restrict_applicable] = false if ::Foreman::Cast.to_bool(params[:errata_restrict_installable]) super end @@ -39,11 +40,11 @@ def custom_index_relation(collection) hosts = ::Host::Managed.authorized("view_hosts") hosts = hosts.where(:organization_id => params[:organization_id]) if params[:organization_id] if ::Foreman::Cast.to_bool(params[:errata_restrict_applicable]) - collection = collection.applicable_to_hosts(hosts) + collection = collection.where(:id => Erratum.applicable_to_hosts(hosts)) end if ::Foreman::Cast.to_bool(params[:errata_restrict_installable]) - collection = collection.installable_for_hosts(hosts) + collection = collection.where(:id => Erratum.ids_installable_for_hosts(hosts)) end collection end diff --git a/app/models/katello/erratum.rb b/app/models/katello/erratum.rb index da7b1c6398c..a65011ab1a6 100644 --- a/app/models/katello/erratum.rb +++ b/app/models/katello/erratum.rb @@ -52,7 +52,7 @@ def self.applicable_to_hosts(hosts) # which is calculated elsewhere. self.joins(:content_facets). - where("#{Katello::Host::ContentFacet.table_name}.host_id" => hosts).uniq + where("#{Katello::Host::ContentFacet.table_name}.host_id" => hosts) end def self.applicable_to_hosts_dashboard(hosts) @@ -89,21 +89,31 @@ def hosts_available(org_id = nil) end def self.installable_for_hosts(hosts = nil) + self.where(:id => ids_installable_for_hosts(hosts)) + end + + def self.ids_installable_for_hosts(hosts = nil) + hosts = ::Host.where(:id => hosts) if hosts && hosts.is_a?(Array) + # Main goal of this query # 1) Get me the applicable errata for these set of hosts # 2) Now further prune this list. Only include errata from repos that have been "enabled" on those hosts. # In other words, prune the list to only include the errate in the "bound" repositories signified by # the inner join between ContentFacetRepository and RepositoryErratum - query = self. + query = self.joins(:content_facet_errata). joins("INNER JOIN #{Katello::ContentFacetRepository.table_name} on \ #{Katello::ContentFacetRepository.table_name}.content_facet_id = #{Katello::ContentFacetErratum.table_name}.content_facet_id"). joins("INNER JOIN #{Katello::RepositoryErratum.table_name} AS host_repo_errata ON \ host_repo_errata.erratum_id = #{Katello::Erratum.table_name}.id AND \ #{Katello::ContentFacetRepository.table_name}.repository_id = host_repo_errata.repository_id") - query = query.joins(:content_facet_errata) unless hosts - query = query.joins(:content_facets).where("#{Katello::Host::ContentFacet.table_name}.host_id" => hosts.map(&:id)) if hosts - query.uniq + if hosts + query = query.where("#{Katello::ContentFacetRepository.table_name}.content_facet_id" => hosts.joins(:content_facet)) + else + query = query.joins(:content_facet_errata) + end + + query end def update_from_json(json) diff --git a/app/models/katello/host/content_facet.rb b/app/models/katello/host/content_facet.rb index cb500939285..7189cfd5e2a 100644 --- a/app/models/katello/host/content_facet.rb +++ b/app/models/katello/host/content_facet.rb @@ -125,7 +125,7 @@ def self.in_content_view_version_environments(version_environments) end def self.with_non_installable_errata(errata) - subquery = Katello::Erratum.select("#{Katello::Erratum.table_name}.id").installable_for_hosts + subquery = Katello::Erratum.select("#{Katello::Erratum.table_name}.id").ids_installable_for_hosts .where("#{Katello::ContentFacetRepository.table_name}.content_facet_id = #{Katello::Host::ContentFacet.table_name}.id").to_sql self.joins(:applicable_errata).where("#{Katello::Erratum.table_name}.id" => errata).where("#{Katello::Erratum.table_name}.id NOT IN (#{subquery})").uniq end