1
0
mirror of https://github.com/ansible/awx.git synced 2024-11-01 08:21:15 +03:00

Merge pull request #1888 from jakemcdermott/fix-1770

make prior output viewable for partial job runs
This commit is contained in:
Jake McDermott 2018-05-22 14:47:18 -04:00 committed by GitHub
commit 156b5e6979
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 44 deletions

View File

@ -29,7 +29,7 @@ function JobEventsApiService ($http, $q) {
this.getLastPage = count => Math.ceil(count / this.state.params.page_size); this.getLastPage = count => Math.ceil(count / this.state.params.page_size);
this.fetch = () => { this.clearCache = () => {
delete this.cache; delete this.cache;
delete this.keys; delete this.keys;
delete this.pageSizes; delete this.pageSizes;
@ -37,10 +37,10 @@ function JobEventsApiService ($http, $q) {
this.cache = {}; this.cache = {};
this.keys = []; this.keys = [];
this.pageSizes = {}; this.pageSizes = {};
return this.getPage(1).then(() => this);
}; };
this.fetch = () => this.first().then(() => this);
this.getPage = number => { this.getPage = number => {
if (number < 1 || number > this.state.last) { if (number < 1 || number > this.state.last) {
return $q.resolve(); return $q.resolve();
@ -79,11 +79,18 @@ function JobEventsApiService ($http, $q) {
return { results, page: number }; return { results, page: number };
}); });
if (number === 1) {
this.clearCache();
}
this.cache[number] = promise; this.cache[number] = promise;
this.keys.push(number); this.keys.push(number);
if (this.keys.length > PAGE_LIMIT) { if (this.keys.length > PAGE_LIMIT) {
delete this.cache[this.keys.shift()]; const remove = this.keys.shift();
delete this.cache[remove];
delete this.pageSizes[remove];
} }
return promise; return promise;
@ -107,17 +114,22 @@ function JobEventsApiService ($http, $q) {
const { results, count } = data; const { results, count } = data;
const lastPage = this.getLastPage(count); const lastPage = this.getLastPage(count);
results.reverse(); if (count > PAGE_SIZE) {
const shifted = results.splice(count % PAGE_SIZE); results.splice(count % PAGE_SIZE);
}
this.state.results = shifted; results.reverse();
this.state.results = results;
this.state.count = count; this.state.count = count;
this.state.page = lastPage; this.state.page = lastPage;
this.state.next = lastPage; this.state.next = lastPage;
this.state.last = lastPage; this.state.last = lastPage;
this.state.previous = Math.max(1, this.state.page - 1); this.state.previous = Math.max(1, this.state.page - 1);
return { results: shifted, page: lastPage }; this.clearCache();
return { results, page: lastPage };
}); });
return promise; return promise;

View File

@ -73,9 +73,8 @@ function JobEventEngine ($q) {
this.buffer = data => { this.buffer = data => {
const pageAdded = this.page.addToBuffer(data); const pageAdded = this.page.addToBuffer(data);
this.pageCount++;
if (pageAdded) { if (pageAdded) {
this.pageCount++;
this.setBatchFrameCount(); this.setBatchFrameCount();
if (this.isPausing()) { if (this.isPausing()) {
@ -117,6 +116,9 @@ function JobEventEngine ($q) {
this.chain = this.chain this.chain = this.chain
.then(() => { .then(() => {
if (!this.isActive()) { if (!this.isActive()) {
if (data.end_line < (this.lines.min)) {
return $q.resolve();
}
this.start(); this.start();
} else if (data.event === JOB_END) { } else if (data.event === JOB_END) {
if (this.isPaused()) { if (this.isPaused()) {
@ -146,6 +148,10 @@ function JobEventEngine ($q) {
this.renderFrame = events => this.hooks.onEventFrame(events) this.renderFrame = events => this.hooks.onEventFrame(events)
.then(() => { .then(() => {
if (this.scroll.isLocked()) {
this.scroll.scrollToBottom();
}
if (this.isEnding()) { if (this.isEnding()) {
const lastEvents = this.page.emptyBuffer(); const lastEvents = this.page.emptyBuffer();

View File

@ -50,8 +50,8 @@ function JobsIndexController (
// Stdout Navigation // Stdout Navigation
vm.scroll = { vm.scroll = {
showBackToTop: false, showBackToTop: false,
home: scrollHome, home: scrollFirst,
end: scrollEnd, end: scrollLast,
down: scrollPageDown, down: scrollPageDown,
up: scrollPageUp up: scrollPageUp
}; };
@ -97,7 +97,14 @@ function init () {
}); });
streaming = false; streaming = false;
return next().then(() => startListening());
if (status.state.running) {
return scrollLast().then(() => startListening());
} else if (!status.state.finished) {
return scrollFirst().then(() => startListening());
}
return scrollLast();
} }
function stopListening () { function stopListening () {
@ -117,30 +124,13 @@ function handleStatusEvent (data) {
function handleJobEvent (data) { function handleJobEvent (data) {
streaming = streaming || attachToRunningJob(); streaming = streaming || attachToRunningJob();
streaming.then(() => { streaming.then(() => {
engine.pushJobEvent(data); engine.pushJobEvent(data);
status.pushJobEvent(data); status.pushJobEvent(data);
}); });
} }
function attachToRunningJob () {
if (!status.state.running) {
return $q.resolve();
}
return page.last()
.then(events => {
if (!events) {
return $q.resolve();
}
const minLine = 1 + Math.max(...events.map(event => event.end_line));
return render.clear()
.then(() => engine.setMinLine(minLine));
});
}
function next () { function next () {
return page.next() return page.next()
.then(events => { .then(events => {
@ -217,8 +207,16 @@ function shift () {
return render.shift(lines); return render.shift(lines);
} }
function scrollHome () { function scrollFirst () {
if (scroll.isPaused()) { if (engine.isActive()) {
if (engine.isTransitioning()) {
return $q.resolve();
}
if (!engine.isPaused()) {
engine.pause(true);
}
} else if (scroll.isPaused()) {
return $q.resolve(); return $q.resolve();
} }
@ -246,19 +244,57 @@ function scrollHome () {
}); });
} }
function scrollEnd () { function scrollLast () {
if (engine.isActive()) { if (engine.isActive()) {
if (engine.isTransitioning()) { if (engine.isTransitioning()) {
return $q.resolve(); return $q.resolve();
} }
if (engine.isPaused()) { if (engine.isPaused()) {
engine.resume(); engine.resume(true);
} else { }
engine.pause(); } else if (scroll.isPaused()) {
return $q.resolve();
}
scroll.pause();
return render.clear()
.then(() => page.last())
.then(events => {
if (!events) {
return $q.resolve();
}
const minLine = 1 + Math.max(...events.map(event => event.end_line));
engine.setMinLine(minLine);
return append(events);
})
.then(() => {
if (!engine.isActive()) {
scroll.resume();
}
scroll.setScrollPosition(scroll.getScrollHeight());
})
.then(() => {
if (!engine.isActive() && scroll.isMissing()) {
return previous();
}
return $q.resolve();
});
}
function attachToRunningJob () {
if (engine.isActive()) {
if (engine.isTransitioning()) {
return $q.resolve();
} }
return $q.resolve(); if (engine.isPaused()) {
engine.resume(true);
}
} else if (scroll.isPaused()) { } else if (scroll.isPaused()) {
return $q.resolve(); return $q.resolve();
} }
@ -271,12 +307,13 @@ function scrollEnd () {
return $q.resolve(); return $q.resolve();
} }
return render.clear() const minLine = 1 + Math.max(...events.map(event => event.end_line));
.then(() => append(events)); engine.setMinLine(minLine);
return append(events);
}) })
.then(() => { .then(() => {
scroll.setScrollPosition(scroll.getScrollHeight()); scroll.setScrollPosition(scroll.getScrollHeight());
scroll.resume();
}); });
} }

View File

@ -17,7 +17,7 @@ function JobPageService ($q) {
this.bookmark = { this.bookmark = {
pending: false, pending: false,
set: false, set: true,
cache: [], cache: [],
state: { state: {
count: 0, count: 0,

View File

@ -4,7 +4,9 @@ const PLAY_START = 'playbook_on_play_start';
const TASK_START = 'playbook_on_task_start'; const TASK_START = 'playbook_on_task_start';
const HOST_STATUS_KEYS = ['dark', 'failures', 'changed', 'ok', 'skipped']; const HOST_STATUS_KEYS = ['dark', 'failures', 'changed', 'ok', 'skipped'];
const FINISHED = ['successful', 'failed', 'error']; const COMPLETE = ['successful', 'failed'];
const INCOMPLETE = ['canceled', 'error'];
const FINISHED = COMPLETE.concat(INCOMPLETE);
function JobStatusService (moment, message) { function JobStatusService (moment, message) {
this.dispatch = () => message.dispatch('status', this.state); this.dispatch = () => message.dispatch('status', this.state);
@ -151,7 +153,10 @@ function JobStatusService (moment, message) {
this.setJobStatus = status => { this.setJobStatus = status => {
this.state.status = status; this.state.status = status;
if (!this.isExpectingStatsEvent() && _.includes(FINISHED, status)) { const isIncomplete = _.includes(INCOMPLETE, status);
const isFinished = _.includes(FINISHED, status);
if ((this.isExpectingStatsEvent() && isIncomplete) || isFinished) {
if (this.latestTime) { if (this.latestTime) {
this.setFinished(this.latestTime); this.setFinished(this.latestTime);
if (!this.state.started && this.state.elapsed) { if (!this.state.started && this.state.elapsed) {