From 503668141bdfcfaa3b6bd326b123687c47f444df Mon Sep 17 00:00:00 2001 From: Jake McDermott Date: Fri, 11 May 2018 22:59:45 -0400 Subject: [PATCH] add procedure for attaching to running jobs --- .../client/features/output/engine.service.js | 10 +-- .../features/output/index.controller.js | 62 +++++++++++++++---- .../client/features/output/status.service.js | 22 +++++-- awx/ui/client/lib/models/Base.js | 8 +++ 4 files changed, 80 insertions(+), 22 deletions(-) diff --git a/awx/ui/client/features/output/engine.service.js b/awx/ui/client/features/output/engine.service.js index 1f74a90c59..2e6371520f 100644 --- a/awx/ui/client/features/output/engine.service.js +++ b/awx/ui/client/features/output/engine.service.js @@ -38,6 +38,12 @@ function JobEventEngine ($q) { }; }; + this.setMinLine = min => { + if (min > this.lines.min) { + this.lines.min = min; + } + }; + this.getBatchFactors = size => { const factors = [1]; @@ -140,10 +146,6 @@ function JobEventEngine ($q) { this.renderFrame = events => this.hooks.onEventFrame(events) .then(() => { - if (this.scroll.isLocked()) { - this.scroll.scrollToBottom(); - } - if (this.isEnding()) { const lastEvents = this.page.emptyBuffer(); diff --git a/awx/ui/client/features/output/index.controller.js b/awx/ui/client/features/output/index.controller.js index 5ba68bc8e6..5f5ba6b6eb 100644 --- a/awx/ui/client/features/output/index.controller.js +++ b/awx/ui/client/features/output/index.controller.js @@ -7,8 +7,10 @@ let resource; let scroll; let engine; let status; +let $http; let vm; +let streaming; let listeners = []; function JobsIndexController ( @@ -21,6 +23,7 @@ function JobsIndexController ( _$compile_, _$q_, _status_, + _$http_, ) { vm = this || {}; @@ -34,6 +37,7 @@ function JobsIndexController ( render = _render_; engine = _engine_; status = _status_; + $http = _$http_; // Development helper(s) vm.clear = devClear; @@ -96,15 +100,8 @@ function init () { } }); - if (!status.state.running) { - next(); - return; - } - - resource.model.get(`related.${resource.related}.results`) - .forEach(handleJobEvent); - - startListening(); + streaming = false; + return next().then(() => startListening()); } function stopListening () { @@ -123,12 +120,46 @@ function handleStatusEvent (data) { } function handleJobEvent (data) { - engine.pushJobEvent(data); - status.pushJobEvent(data); + streaming = streaming || attachToRunningJob(); + streaming.then(() => { + engine.pushJobEvent(data); + status.pushJobEvent(data); + }); } -function devClear () { - render.clear().then(() => init()); +function attachToRunningJob () { + const target = `${resource.model.get('url')}${resource.related}/`; + const params = { order_by: '-created', page_size: resource.page.size }; + + scroll.pause(); + + return render.clear() + .then(() => $http.get(target, { params })) + .then(res => { + const { results } = res.data; + + const minLine = 1 + Math.max(...results.map(event => event.end_line)); + const maxCount = Math.max(...results.map(event => event.counter)); + + const lastPage = resource.model.updateCount(maxCount); + + page.emptyCache(lastPage); + page.addPage(lastPage, [], true); + + engine.setMinLine(minLine); + + if (resource.model.page.current === lastPage) { + return $q.resolve(); + } + + return append(results); + }) + .then(() => { + scroll.setScrollPosition(scroll.getScrollHeight()); + scroll.resume(); + + return $q.resolve(); + }); } function next () { @@ -294,6 +325,10 @@ function toggleExpanded () { vm.expanded = !vm.expanded; } +function devClear () { + render.clear().then(() => init()); +} + // function showHostDetails (id) { // jobEvent.request('get', id) // .then(() => { @@ -344,6 +379,7 @@ JobsIndexController.$inject = [ '$compile', '$q', 'JobStatusService', + '$http', ]; module.exports = JobsIndexController; diff --git a/awx/ui/client/features/output/status.service.js b/awx/ui/client/features/output/status.service.js index 12e3fd2544..a4e60c6822 100644 --- a/awx/ui/client/features/output/status.service.js +++ b/awx/ui/client/features/output/status.service.js @@ -49,48 +49,60 @@ function JobStatusService (moment, message) { }; this.pushStatusEvent = data => { - const isJobEvent = (this.job === data.unified_job_id); - const isProjectEvent = (this.project && (this.project === data.project_id)); + const isJobStatusEvent = (this.job === data.unified_job_id); + const isProjectStatusEvent = (this.project && (this.project === data.project_id)); - if (isJobEvent) { + if (isJobStatusEvent) { this.setJobStatus(data.status); - } else if (isProjectEvent) { + this.dispatch(); + } else if (isProjectStatusEvent) { this.setProjectStatus(data.status); this.setProjectUpdateId(data.unified_job_id); + this.dispatch(); } }; this.pushJobEvent = data => { const isLatest = ((!this.counter) || (data.counter > this.counter)); + let changed = false; + if (!this.active && !(data.event === JOB_END)) { this.active = true; this.setJobStatus('running'); + changed = true; } if (isLatest) { this.counter = data.counter; this.latestTime = data.created; this.setElapsed(moment(data.created).diff(this.created, 'seconds')); + changed = true; } if (data.event === JOB_START) { this.setStarted(this.state.started || data.created); + changed = true; } if (data.event === PLAY_START) { this.state.counts.plays++; + changed = true; } if (data.event === TASK_START) { this.state.counts.tasks++; + changed = true; } if (data.event === JOB_END) { this.setStatsEvent(data); + changed = true; } - this.dispatch(); + if (changed) { + this.dispatch(); + } }; this.isExpectingStatsEvent = () => (this.jobType === 'job') || diff --git a/awx/ui/client/lib/models/Base.js b/awx/ui/client/lib/models/Base.js index 912d9a984c..a7cc321806 100644 --- a/awx/ui/client/lib/models/Base.js +++ b/awx/ui/client/lib/models/Base.js @@ -398,6 +398,13 @@ function extend (method, related, config = {}) { return Promise.reject(new Error(`No related property, ${related}, exists`)); } +function updateCount (count) { + this.page.count = count; + this.page.last = Math.ceil(count / this.page.size); + + return this.page.last; +} + function goToPage (config) { const params = config.params || {}; const { page } = config; @@ -693,6 +700,7 @@ function BaseModel (resource, settings) { this.extend = extend; this.copy = copy; this.getDependentResourceCounts = getDependentResourceCounts; + this.updateCount = updateCount; this.http = { get: httpGet.bind(this),