render missing lines instead of auto-unfollowing

This commit is contained in:
Jake McDermott 2018-08-20 23:20:40 -04:00
parent 138f8a45ae
commit 0bc9b1d431
No known key found for this signature in database
GPG Key ID: 9A6F084352C3A0B7
3 changed files with 154 additions and 88 deletions

View File

@ -31,12 +31,6 @@ function onFrames (events) {
}
const popCount = events.length - render.getCapacity();
const isAttached = events.length > 0;
if (!isAttached) {
stopFollowing();
return $q.resolve();
}
if (!vm.isFollowing && canStartFollowing()) {
startFollowing();
@ -58,7 +52,7 @@ function onFrames (events) {
scroll.scrollToBottom();
}
return render.pushFrames(events);
return render.pushFront(events);
})
.then(() => {
if (vm.isFollowing) {
@ -80,11 +74,18 @@ function firstRange () {
return $q.resolve();
}
stopFollowing();
lockFollow = true;
if (slide.isOnFirstPage()) {
scroll.resetScrollPosition();
return $q.resolve();
}
scroll.pause();
lockFrames = true;
stopFollowing();
return render.clear()
.then(() => slide.getFirst())
.then(results => render.pushFront(results))
@ -97,7 +98,7 @@ function firstRange () {
})
.finally(() => {
scroll.resume();
lockFrames = false;
lockFollow = false;
});
}
@ -112,10 +113,6 @@ function nextRange () {
return $q.resolve();
}
if (slide.getTailCounter() >= slide.getMaxCounter()) {
return $q.resolve();
}
scroll.pause();
lockFrames = true;
@ -129,6 +126,8 @@ function nextRange () {
.finally(() => {
scroll.resume();
lockFrames = false;
return $q.resolve();
});
}
@ -138,8 +137,8 @@ function previousRange () {
}
scroll.pause();
lockFrames = true;
stopFollowing();
lockFrames = true;
let initialPosition;
let popHeight;
@ -182,13 +181,15 @@ function lastRange () {
.then(() => slide.getLast())
.then(results => render.pushFront(results))
.then(() => {
stream.setMissingCounterThreshold(slide.getTailCounter() + 1);
scroll.scrollToBottom();
lockFrames = false;
return $q.resolve();
})
.finally(() => {
scroll.resume();
lockFrames = false;
return $q.resolve();
});
@ -204,13 +205,12 @@ function menuLastRange () {
lockFollow = false;
if (slide.isOnLastPage()) {
scroll.scrollToBottom();
return lastRange()
.then(() => {
startFollowing();
return $q.resolve();
}
return last();
return $q.resolve();
});
}
let followOnce;

View File

@ -58,6 +58,9 @@ function JobRenderService ($q, $sce, $window) {
this.setCollapseAll = value => {
this.state.collapseAll = value;
Object.keys(this.records).forEach(key => {
this.records[key].isCollapsed = value;
});
};
this.sortByCounter = (a, b) => {
@ -76,7 +79,7 @@ function JobRenderService ($q, $sce, $window) {
// Event Data Transformation / HTML Building
//
this.transformEventGroup = (events, streaming = false) => {
this.appendEventGroup = events => {
let lines = 0;
let html = '';
@ -84,16 +87,13 @@ function JobRenderService ($q, $sce, $window) {
for (let i = 0; i <= events.length - 1; i++) {
const current = events[i];
const tailCounter = this.getTailCounter();
if (streaming) {
const tailCounter = this.getTailCounter();
if (tailCounter && (current.counter !== tailCounter + 1)) {
const missing = this.appendMissingEventGroup(current);
if (tailCounter && (current.counter !== tailCounter + 1)) {
const missing = this.transformMissingEventGroup(current);
html += missing.html;
lines += missing.count;
}
html += missing.html;
lines += missing.count;
}
const line = this.transformEvent(current);
@ -105,21 +105,39 @@ function JobRenderService ($q, $sce, $window) {
return { html, lines };
};
this.transformMissingEventGroup = event => {
const tail = this.lookupRecord(this.getTailCounter());
this.appendMissingEventGroup = event => {
const tailCounter = this.getTailCounter();
const tail = this.lookupRecord(tailCounter);
const tailMissing = this.isCounterMissing(tailCounter);
if (!tail || !tail.counter) {
if (!tailMissing && (!tail || !tail.counter)) {
return { html: '', count: 0 };
}
const uuid = getUUID();
let uuid;
if (tailMissing) {
uuid = this.missingCounterUUIDs[tailCounter];
} else {
uuid = getUUID();
}
const counters = [];
for (let i = tail.counter + 1; i < event.counter; i++) {
counters.push(i);
for (let i = tailCounter + 1; i < event.counter; i++) {
if (tailMissing) {
this.missingCounterRecords[uuid].counters.push(i);
} else {
counters.push(i);
}
this.missingCounterUUIDs[i] = uuid;
}
if (tailMissing) {
return { html: '', count: 0 };
}
const record = {
counters,
uuid,
@ -127,6 +145,90 @@ function JobRenderService ($q, $sce, $window) {
end: event.start_line,
};
if (record.start === record.end) {
return { html: '', count: 0 };
}
this.missingCounterRecords[uuid] = record;
const html = `<div id="${uuid}" class="at-Stdout-row">
<div class="at-Stdout-toggle"></div>
<div class="at-Stdout-line-clickable" ng-click="vm.showMissingEvents('${uuid}')">...</div></div>`;
const count = 1;
return { html, count };
};
this.prependEventGroup = events => {
let lines = 0;
let html = '';
events.sort(this.sortByCounter);
for (let i = events.length - 1; i >= 0; i--) {
const current = events[i];
const headCounter = this.getHeadCounter();
if (headCounter && (current.counter !== headCounter - 1)) {
const missing = this.prependMissingEventGroup(current);
html = missing.html + html;
lines += missing.count;
}
const line = this.transformEvent(current);
html = line.html + html;
lines += line.count;
}
return { html, lines };
};
this.prependMissingEventGroup = event => {
const headCounter = this.getHeadCounter();
const head = this.lookupRecord(headCounter);
const headMissing = this.isCounterMissing(headCounter);
if (!headMissing && (!head || !head.counter)) {
return { html: '', count: 0 };
}
let uuid;
if (headMissing) {
uuid = this.missingCounterUUIDs[headCounter];
} else {
uuid = getUUID();
}
const counters = [];
for (let i = headCounter - 1; i > event.counter; i--) {
if (headMissing) {
this.missingCounterRecords[uuid].counters.unshift(i);
} else {
counters.unshift(i);
}
this.missingCounterUUIDs[i] = uuid;
}
if (headMissing) {
return { html: '', count: 0 };
}
const record = {
counters,
uuid,
start: event.end_line,
end: head.start,
};
if (record.start === record.end) {
return { html: '', count: 0 };
}
this.missingCounterRecords[uuid] = record;
const html = `<div id="${uuid}" class="at-Stdout-row">
@ -401,7 +503,7 @@ function JobRenderService ($q, $sce, $window) {
return $q.resolve();
}
const result = this.transformEventGroup(events);
const result = this.prependEventGroup(events);
const html = this.trustHtml(result.html);
const newElements = angular.element(html);
@ -411,12 +513,12 @@ function JobRenderService ($q, $sce, $window) {
.then(() => result.lines);
};
this.append = (events, streaming = false) => {
this.append = events => {
if (events.length < 1) {
return $q.resolve();
}
const result = this.transformEventGroup(events, streaming);
const result = this.appendEventGroup(events);
const html = this.trustHtml(result.html);
const newElements = angular.element(html);
@ -498,10 +600,10 @@ function JobRenderService ($q, $sce, $window) {
return $q.resolve();
});
this.pushFront = (events, streaming = false) => {
this.pushFront = events => {
const tail = this.getTailCounter();
return this.append(events.filter(({ counter }) => counter > tail), streaming);
return this.append(events.filter(({ counter }) => counter > tail));
};
this.pushBack = events => {
@ -511,8 +613,6 @@ function JobRenderService ($q, $sce, $window) {
return this.prepend(events.filter(({ counter }) => counter < head || counter > tail));
};
this.pushFrames = events => this.pushFront(events, true);
this.popMissing = counter => {
const uuid = this.missingCounterUUIDs[counter];

View File

@ -1,37 +1,9 @@
/* eslint camelcase: 0 */
import {
OUTPUT_EVENT_LIMIT,
OUTPUT_MAX_BUFFER_LENGTH,
OUTPUT_PAGE_SIZE,
} from './constants';
function getContinuous (events, reverse = false) {
const counters = events.map(({ counter }) => counter);
const min = Math.min(...counters);
const max = Math.max(...counters);
const missing = [];
for (let i = min; i <= max; i++) {
if (counters.indexOf(i) < 0) {
missing.push(i);
}
}
if (missing.length === 0) {
return events;
}
if (reverse) {
const threshold = Math.max(...missing);
return events.filter(({ counter }) => counter > threshold);
}
const threshold = Math.min(...missing);
return events.filter(({ counter }) => counter < threshold);
}
function SlidingWindowService ($q) {
this.init = ({ getRange, getFirst, getLast, getMaxCounter }, storage) => {
const { getHeadCounter, getTailCounter } = storage;
@ -81,15 +53,13 @@ function SlidingWindowService ($q) {
this.getNext = (displacement = OUTPUT_PAGE_SIZE) => {
const next = this.getNextRange(displacement);
return this.api.getRange(next)
.then(results => getContinuous(results));
return this.api.getRange(next);
};
this.getPrevious = (displacement = OUTPUT_PAGE_SIZE) => {
const previous = this.getPreviousRange(displacement);
return this.api.getRange(previous)
.then(results => getContinuous(results, true));
return this.api.getRange(previous);
};
this.getFirst = () => {
@ -128,7 +98,7 @@ function SlidingWindowService ($q) {
for (let i = frames.length - 1; i >= 0; i--) {
count++;
if (count > OUTPUT_EVENT_LIMIT) {
if (count > OUTPUT_MAX_BUFFER_LENGTH) {
frames.splice(i, 1);
count--;
@ -153,29 +123,25 @@ function SlidingWindowService ($q) {
return frames;
}
if (min >= head && min <= tail + 1) {
return frames.filter(({ counter }) => counter > tail);
}
return [];
return frames.filter(({ counter }) => counter > tail);
};
this.getFrames = () => $q.resolve(this.buffer.events);
this.getMaxCounter = () => {
if (this.buffer.min && this.buffer.min > 1) {
return this.buffer.min - 1;
if (this.buffer.max && this.buffer.max > 1) {
return this.buffer.max;
}
return this.api.getMaxCounter();
};
this.isOnLastPage = () => {
if (this.getTailCounter() === 0) {
return true;
if (this.buffer.min) {
return this.getTailCounter() >= this.buffer.min - 1;
}
return this.getTailCounter() >= (this.getMaxCounter() - OUTPUT_PAGE_SIZE);
return this.getTailCounter() >= this.getMaxCounter() - OUTPUT_PAGE_SIZE;
};
this.isOnFirstPage = () => this.getHeadCounter() === 1;