From 60a137225aba1e09dd193fe17120ca227ef96aca Mon Sep 17 00:00:00 2001 From: mabashian Date: Mon, 17 Feb 2020 16:52:08 -0500 Subject: [PATCH] Changes how the jobs list reacts to socket messages. We now only make targeted GET requests for new rows. We use the available information in the socket message to update the relevant row (if visible in the list). --- .../features/jobs/jobsList.controller.js | 104 +++++++++++++----- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/awx/ui/client/features/jobs/jobsList.controller.js b/awx/ui/client/features/jobs/jobsList.controller.js index 2a7225de6a..986ad12f8e 100644 --- a/awx/ui/client/features/jobs/jobsList.controller.js +++ b/awx/ui/client/features/jobs/jobsList.controller.js @@ -25,15 +25,15 @@ function ListJobsController ( vm.strings = strings; + let newJobs = []; + // smart-search const name = 'jobs'; const iterator = 'job'; let paginateQuerySet = {}; let launchModalOpen = false; - let refreshAfterLaunchClose = false; - let pendingRefresh = false; - let refreshTimerRunning = false; + let newJobsTimerRunning = false; vm.searchBasePath = SearchBasePath; @@ -104,23 +104,44 @@ function ListJobsController ( $scope.$emit('updateCount', vm.job_dataset.count, 'jobs'); }); - $scope.$on('ws-jobs', () => { - if (!launchModalOpen) { - if (!refreshTimerRunning) { - refreshJobs(); - } else { - pendingRefresh = true; + const canAddRowsDynamically = () => { + const orderByValue = _.get($state.params, 'job_search.order_by'); + const pageValue = _.get($state.params, 'job_search.page'); + const idInValue = _.get($state.params, 'job_search.id__in'); + + return (!idInValue && (!pageValue || pageValue === '1') + && (orderByValue === '-finished' || orderByValue === '-started')); + }; + + const updateJobRow = (msg) => { + // Loop across the jobs currently shown and update the row + // if it exists + for (let i = 0; i < vm.jobs.length; i++) { + if (vm.jobs[i].id === msg.unified_job_id) { + // Update the job status. + // If/when we get more info in the message we can + // update those fields here as well. + vm.jobs[i].status = msg.status; + i = vm.jobs.length; } - } else { - refreshAfterLaunchClose = true; + } + }; + + $scope.$on('ws-jobs', (e, msg) => { + if (msg.status === 'pending' && canAddRowsDynamically()) { + newJobs.push(msg.unified_job_id); + if (!launchModalOpen && !newJobsTimerRunning) { + fetchNewJobs(); + } + } else if (!newJobs.includes(msg.unified_job_id)) { + updateJobRow(msg); } }); $scope.$on('launchModalOpen', (evt, isOpen) => { evt.stopPropagation(); - if (!isOpen && refreshAfterLaunchClose) { - refreshAfterLaunchClose = false; - refreshJobs(); + if (!isOpen && newJobs.length > 0) { + fetchNewJobs(); } launchModalOpen = isOpen; }); @@ -289,22 +310,49 @@ function ListJobsController ( }); }; - function refreshJobs () { - qs.search(SearchBasePath, $state.params.job_search, { 'X-WS-Session-Quiet': true }) + const fetchNewJobs = () => { + newJobsTimerRunning = true; + const newJobIdsFilter = newJobs.join(','); + newJobs = []; + const newJobsSearchParams = Object.assign({}, $state.params.job_search); + newJobsSearchParams.count_disabled = 1; + newJobsSearchParams.id__in = newJobIdsFilter; + delete newJobsSearchParams.page_size; + const stringifiedSearchParams = qs.encodeQueryset(newJobsSearchParams, false); + Rest.setUrl(`${vm.searchBasePath}${stringifiedSearchParams}`); + Rest.get() .then(({ data }) => { - vm.jobs = data.results; - vm.job_dataset = data; + vm.job_dataset.count += data.results.length; + const pageSize = parseInt($state.params.job_search.page_size, 10) || 20; + const joinedJobs = data.results.concat(vm.jobs); + vm.jobs = joinedJobs.length > pageSize + ? joinedJobs.slice(0, pageSize) + : joinedJobs; + $timeout(() => { + if (canAddRowsDynamically()) { + if (newJobs.length > 0 && !launchModalOpen) { + fetchNewJobs(); + } else { + newJobsTimerRunning = false; + } + } else { + // Bail out - one of [order_by, page, id__in] params has changed since we + // received these new job messages + newJobs = []; + newJobsTimerRunning = false; + } + }, 5000); + }) + .catch(({ data, status }) => { + ProcessErrors($scope, data, status, null, { + hdr: strings.get('error.HEADER'), + msg: strings.get('error.CALL', { + path: `${vm.searchBasePath}${stringifiedSearchParams}`, + status + }) + }); }); - pendingRefresh = false; - refreshTimerRunning = true; - $timeout(() => { - if (pendingRefresh) { - refreshJobs(); - } else { - refreshTimerRunning = false; - } - }, 5000); - } + }; vm.isCollapsed = true;