From 3949f643d352768bfeb605440076a3efe749edd1 Mon Sep 17 00:00:00 2001 From: Adam Ruzicka Date: Tue, 26 May 2026 10:31:48 +0200 Subject: [PATCH 1/4] Fixes #39362 - Only load current page of hosts @hosts.to_a materializes all the hosts. Previously it read all the hosts in the job, with this change it reads only the current page. --- .../api/v2/job_invocations_controller.rb | 2 +- .../api/v2/job_invocations_controller_test.rb | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v2/job_invocations_controller.rb b/app/controllers/api/v2/job_invocations_controller.rb index 449da9b91..340bfdc26 100644 --- a/app/controllers/api/v2/job_invocations_controller.rb +++ b/app/controllers/api/v2/job_invocations_controller.rb @@ -115,10 +115,10 @@ def output param :id, :identifier, :required => true def hosts set_hosts_and_template_invocations - set_statuses_and_smart_proxies @total = @hosts.size @hosts = @hosts.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page], :per_page => params[:per_page]) @subtotal = @hosts.total_entries + set_statuses_and_smart_proxies if params[:awaiting] @hosts = @hosts.select { |host| @host_statuses[host.id] == 'N/A' } end diff --git a/test/functional/api/v2/job_invocations_controller_test.rb b/test/functional/api/v2/job_invocations_controller_test.rb index 5c4835e28..6c5fea2ee 100644 --- a/test/functional/api/v2/job_invocations_controller_test.rb +++ b/test/functional/api/v2/job_invocations_controller_test.rb @@ -235,6 +235,23 @@ class JobInvocationsControllerTest < ActionController::TestCase end end + describe '#hosts' do + test 'should compute job_status for the paginated subset' do + invocation = FactoryBot.create(:job_invocation, :with_template, :with_task) + 2.times { invocation.template_invocations << FactoryBot.create(:template_invocation, :with_task, :with_host, :job_invocation => invocation) } + invocation.job_category = invocation.pattern_template_invocations.first.template.job_category + invocation.targeting.hosts = invocation.template_invocations.map(&:host) + invocation.save! + + get :hosts, params: { :id => invocation.id, :page => 2, :per_page => 1 } + assert_response :success + result = ActiveSupport::JSON.decode(@response.body) + assert_equal 3, result['total'] + assert_equal 1, result['results'].size + assert_equal(['success'], result['results'].map { |r| r['job_status'] }) + end + end + describe 'raw output' do let(:fake_output) do (1..5).map do |i| From 777dbe4495fb0368b85723a716ff44913a1126ad Mon Sep 17 00:00:00 2001 From: Adam Ruzicka Date: Tue, 26 May 2026 10:32:46 +0200 Subject: [PATCH 2/4] Fixes #39363 - Do not ask for host statuses when reading job invocation details The extra data it gave doesn't seem to be used anywhere in the job invocation details page. --- .../__tests__/MainInformation.test.js | 9 ++++++--- webpack/JobInvocationDetail/index.js | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/webpack/JobInvocationDetail/__tests__/MainInformation.test.js b/webpack/JobInvocationDetail/__tests__/MainInformation.test.js index e3e62c0dc..90f04640a 100644 --- a/webpack/JobInvocationDetail/__tests__/MainInformation.test.js +++ b/webpack/JobInvocationDetail/__tests__/MainInformation.test.js @@ -35,8 +35,11 @@ jest.spyOn(api, 'get'); const originalToLocaleString = Date.prototype.toLocaleString; beforeAll(() => { // eslint-disable-next-line no-extend-native - Date.prototype.toLocaleString = function (locale, options) { - return originalToLocaleString.call(this, locale, { ...options, timeZone: 'UTC' }); + Date.prototype.toLocaleString = function(locale, options) { + return originalToLocaleString.call(this, locale, { + ...options, + timeZone: 'UTC', + }); }; }); afterAll(() => { @@ -232,7 +235,7 @@ describe('JobInvocationDetailPage', () => { { key: GET_REPORT_TEMPLATES, url: '/api/report_templates' }, { key: JOB_INVOCATION_KEY, - url: `/api/job_invocations/${jobId}?host_status=true`, + url: `/api/job_invocations/${jobId}`, }, { key: GET_REPORT_TEMPLATE_INPUTS, diff --git a/webpack/JobInvocationDetail/index.js b/webpack/JobInvocationDetail/index.js index 6b266241b..34fc19443 100644 --- a/webpack/JobInvocationDetail/index.js +++ b/webpack/JobInvocationDetail/index.js @@ -72,7 +72,7 @@ const JobInvocationDetailPage = ({ } useEffect(() => { - dispatch(getJobInvocation(`/api/job_invocations/${id}?host_status=true`)); + dispatch(getJobInvocation(`/api/job_invocations/${id}`)); if (finished && !autoRefresh) { dispatch(stopInterval(JOB_INVOCATION_KEY)); } From 364e037ac14c55d21794f89ce3519687d4f40509 Mon Sep 17 00:00:00 2001 From: Adam Ruzicka Date: Tue, 26 May 2026 10:34:07 +0200 Subject: [PATCH 3/4] to_h over Hash[col.map { ... }] It's a bit easier on the eyes --- app/controllers/api/v2/job_invocations_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v2/job_invocations_controller.rb b/app/controllers/api/v2/job_invocations_controller.rb index 340bfdc26..a6de39176 100644 --- a/app/controllers/api/v2/job_invocations_controller.rb +++ b/app/controllers/api/v2/job_invocations_controller.rb @@ -313,13 +313,13 @@ def set_hosts_and_template_invocations def set_statuses_and_smart_proxies template_invocations = @template_invocations.includes(:run_host_job_task).to_a hosts = @hosts.to_a - @host_statuses = Hash[hosts.map do |host| + @host_statuses = hosts.to_h do |host| template_invocation = template_invocations.find { |ti| ti.host_id == host.id } task = template_invocation.try(:run_host_job_task) [host.id, template_invocation_status(task, @job_invocation.task)] - end] - @smart_proxy_id = Hash[template_invocations.map { |ti| [ti.host_id, ti.smart_proxy_id] }] - @smart_proxy_name = Hash[template_invocations.map { |ti| [ti.host_id, ti.smart_proxy_name] }] + end + @smart_proxy_id = template_invocations.to_h { |ti| [ti.host_id, ti.smart_proxy_id] } + @smart_proxy_name = template_invocations.to_h { |ti| [ti.host_id, ti.smart_proxy_name] } end end end From 74b79b38027aebe6b5a33a7d85a43b16e119a182 Mon Sep 17 00:00:00 2001 From: Adam Ruzicka Date: Tue, 26 May 2026 15:18:17 +0200 Subject: [PATCH 4/4] Use hash for host -> template invocation lookup --- app/controllers/api/v2/job_invocations_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/v2/job_invocations_controller.rb b/app/controllers/api/v2/job_invocations_controller.rb index a6de39176..5484440bf 100644 --- a/app/controllers/api/v2/job_invocations_controller.rb +++ b/app/controllers/api/v2/job_invocations_controller.rb @@ -313,8 +313,9 @@ def set_hosts_and_template_invocations def set_statuses_and_smart_proxies template_invocations = @template_invocations.includes(:run_host_job_task).to_a hosts = @hosts.to_a + template_invocations_by_host_id = template_invocations.index_by(&:host_id) @host_statuses = hosts.to_h do |host| - template_invocation = template_invocations.find { |ti| ti.host_id == host.id } + template_invocation = template_invocations_by_host_id[host.id] task = template_invocation.try(:run_host_job_task) [host.id, template_invocation_status(task, @job_invocation.task)] end