From e6bba3ed481ff9bd10ccd1a71cd1dd4a0e55b983 Mon Sep 17 00:00:00 2001 From: Chris Houseknecht Date: Fri, 13 Jun 2014 16:39:35 -0400 Subject: [PATCH] Job detail page refactor Added an event queue, allowing the UI to process events as fast as it can and hopefully not get overwhelmed by the API. --- awx/ui/static/js/controllers/JobDetail.js | 27 +++++++----- awx/ui/static/js/helpers/JobDetail.js | 50 ++++++++++++++++++++--- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/awx/ui/static/js/controllers/JobDetail.js b/awx/ui/static/js/controllers/JobDetail.js index c4bd10d4fd..3cf1949aae 100644 --- a/awx/ui/static/js/controllers/JobDetail.js +++ b/awx/ui/static/js/controllers/JobDetail.js @@ -59,18 +59,16 @@ function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, event_socket.init(); event_socket.on("job_events-" + job_id, function(data) { - if (api_complete && data.id > lastEventId) { + data.event = data.event_name; + $log.debug('push event: ' + data.id); + event_queue.push(data); + + /* if (api_complete && data.id > lastEventId) { // api loading is complete, process incoming events - data.event = data.event_name; - DigestEvents({ - scope: scope, - events: [ data ] - }); } else { // Waiting on values from the api to load. Until then queue incoming events. - event_queue.push(data); - } + } */ }); if (scope.removeAPIComplete) { @@ -78,7 +76,7 @@ function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, } scope.removeAPIComplete = scope.$on('APIComplete', function() { // process any events sitting in the queue - var events = [], url, hostId = 0, taskId = 0, playId = 0; + var url, hostId = 0, taskId = 0, playId = 0; function notEmpty(x) { return Object.keys(x).length > 0; @@ -103,7 +101,7 @@ function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, lastEventId = Math.max(hostId, taskId, playId); // Only process queued events > the max event in memory - if (event_queue.length > 0) { + /*if (event_queue.length > 0) { event_queue.forEach(function(event) { if (event.id > lastEventId) { events.push(event); @@ -115,7 +113,14 @@ function JobDetailController ($scope, $compile, $routeParams, $log, ClearScope, events: events }); } - } + }*/ + + DigestEvents({ + scope: scope, + queue: event_queue, + lastEventId: lastEventId + }); + api_complete = true; // Draw the graph diff --git a/awx/ui/static/js/helpers/JobDetail.js b/awx/ui/static/js/helpers/JobDetail.js index e9243f27fb..acef8cf254 100644 --- a/awx/ui/static/js/helpers/JobDetail.js +++ b/awx/ui/static/js/helpers/JobDetail.js @@ -39,17 +39,45 @@ angular.module('JobDetailHelper', ['Utilities', 'RestServices']) -.factory('DigestEvents', ['UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult', 'SelectPlay', 'SelectTask', +.factory('DigestEvents', ['$log', 'UpdatePlayStatus', 'UpdateHostStatus', 'AddHostResult', 'SelectPlay', 'SelectTask', 'GetHostCount', 'GetElapsed', 'UpdateTaskStatus', 'DrawGraph', 'LoadHostSummary', -function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed, +function($log, UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTask, GetHostCount, GetElapsed, UpdateTaskStatus, DrawGraph, LoadHostSummary) { return function(params) { var scope = params.scope, - events = params.events; + queue = params.queue, + lastEventId = params.lastEventId, + myInterval; - events.forEach(function(event) { + if (scope.removeGetNextEvent) { + scope.removeGetNextEvent(); + } + scope.removeGetNextEvent = scope.$on('GetNextEvent', function() { + if (myInterval) { + window.clearInterval(myInterval); + } + if (scope.job.status !== 'successful' && scope.job.status !== 'failed' && scope.job.status !== 'error') { + myInterval = window.setInterval(function() { + var event; + $log.debug('checking queue length is: ' + queue.length); + if (queue.length > 0) { + event = queue.splice(0,1); + if (event[0].id > lastEventId) { + $log.debug('processing event: ' + event[0].id); + scope.$emit('ProcessEvent', event[0]); + } + } + }, 2000); + } + }); + + if (scope.removeProcessEvent) { + scope.removeProcessEvent(); + } + scope.removeProcessEvent = scope.$on('ProcessEvent', function(e, event) { var hostCount; + $log.debug('handling event: ' + event.id); if (event.event === 'playbook_on_start') { if (scope.job_status.status!== 'failed' && scope.job_status.status !== 'canceled' && scope.job_status.status !== 'error' && scope.job_status !== 'successful') { @@ -117,6 +145,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, status_text: 'failed- no hosts matched' }); + scope.$emit('GetNextEvent'); } if (event.event === 'playbook_on_task_start') { if (scope.activePlay === event.parent) { @@ -159,6 +188,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa changed: event.changed, modified: event.modified }); + scope.$emit('GetNextEvent'); } if (event.event === 'runner_on_unreachable') { @@ -173,7 +203,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, message: ( (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' ) }); - + scope.$emit('GetNextEvent'); } if (event.event === 'runner_on_error' || event.event === 'runner_on_async_failed') { UpdateHostStatus({ @@ -187,6 +217,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, message: (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' }); + scope.$emit('GetNextEvent'); } if (event.event === 'runner_on_no_hosts') { UpdateTaskStatus({ @@ -197,6 +228,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, no_hosts: true }); + scope.$emit('GetNextEvent'); } if (event.event === 'runner_on_skipped') { UpdateHostStatus({ @@ -210,6 +242,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, message: (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' }); + scope.$emit('GetNextEvent'); } if (event.event === 'runner_on_ok' || event.event === 'runner_on_async_ok') { UpdateHostStatus({ @@ -223,6 +256,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa modified: event.modified, message: (event.event_data && event.event_data.res) ? event.event_data.res.msg : '' }); + scope.$emit('GetNextEvent'); } if (event.event === 'playbook_on_stats') { scope.job_status.finished = event.modified; @@ -235,8 +269,12 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa scope.host_summary = {}; LoadHostSummary({ scope: scope, data: event.event_data }); DrawGraph({ scope: scope, resize: true }); + scope.$emit('GetNextEvent'); } }); + + scope.$emit('GetNextEvent'); + }; }]) @@ -753,6 +791,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa scope.$emit(callback); } SelectHost({ scope: scope }); + scope.$emit('GetNextEvent'); }) .error(function(data, status) { ProcessErrors(scope, data, status, null, { hdr: 'Error!', @@ -764,6 +803,7 @@ function(UpdatePlayStatus, UpdateHostStatus, AddHostResult, SelectPlay, SelectTa scope.$emit(callback); } SelectHost({ scope: scope }); + scope.$emit('GetNextEvent'); } }; }])