mirror of
https://github.com/ansible/awx.git
synced 2024-11-01 16:51:11 +03:00
maintain correct page counts on running jobs
This commit is contained in:
parent
503668141b
commit
11e7dcd0dc
132
awx/ui/client/features/output/api.events.service.js
Normal file
132
awx/ui/client/features/output/api.events.service.js
Normal file
@ -0,0 +1,132 @@
|
||||
const PAGE_LIMIT = 5;
|
||||
const PAGE_SIZE = 50;
|
||||
|
||||
const BASE_PARAMS = {
|
||||
order_by: 'start_line',
|
||||
page_size: PAGE_SIZE,
|
||||
};
|
||||
|
||||
const merge = (...objs) => _.merge({}, ...objs);
|
||||
|
||||
const getInitialState = params => ({
|
||||
results: [],
|
||||
count: 0,
|
||||
previous: 1,
|
||||
page: 1,
|
||||
next: 1,
|
||||
last: 1,
|
||||
params: merge(BASE_PARAMS, params),
|
||||
});
|
||||
|
||||
function JobEventsApiService ($http, $q) {
|
||||
this.init = (endpoint, params) => {
|
||||
this.keys = [];
|
||||
this.cache = {};
|
||||
this.pageSizes = {};
|
||||
this.endpoint = endpoint;
|
||||
this.state = getInitialState(params);
|
||||
};
|
||||
|
||||
this.getLastPage = count => Math.ceil(count / this.state.params.page_size);
|
||||
|
||||
this.fetch = () => {
|
||||
delete this.cache;
|
||||
delete this.keys;
|
||||
delete this.pageSizes;
|
||||
|
||||
this.cache = {};
|
||||
this.keys = [];
|
||||
this.pageSizes = {};
|
||||
|
||||
return this.getPage(1).then(() => this);
|
||||
};
|
||||
|
||||
this.getPage = number => {
|
||||
if (number < 1 || number > this.state.last) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
if (this.cache[number]) {
|
||||
if (this.pageSizes[number] === PAGE_SIZE) {
|
||||
return this.cache[number];
|
||||
}
|
||||
|
||||
delete this.pageSizes[number];
|
||||
delete this.cache[number];
|
||||
|
||||
this.keys.splice(this.keys.indexOf(number));
|
||||
}
|
||||
|
||||
const { params } = this.state;
|
||||
|
||||
delete params.page;
|
||||
|
||||
params.page = number;
|
||||
|
||||
const promise = $http.get(this.endpoint, { params })
|
||||
.then(({ data }) => {
|
||||
const { results, count } = data;
|
||||
|
||||
this.state.results = results;
|
||||
this.state.count = count;
|
||||
this.state.page = number;
|
||||
this.state.last = this.getLastPage(count);
|
||||
this.state.previous = Math.max(1, number - 1);
|
||||
this.state.next = Math.min(this.state.last, number + 1);
|
||||
|
||||
this.pageSizes[number] = results.length;
|
||||
|
||||
return { results, page: number };
|
||||
});
|
||||
|
||||
this.cache[number] = promise;
|
||||
this.keys.push(number);
|
||||
|
||||
if (this.keys.length > PAGE_LIMIT) {
|
||||
delete this.cache[this.keys.shift()];
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
this.first = () => this.getPage(1);
|
||||
this.next = () => this.getPage(this.state.next);
|
||||
this.previous = () => this.getPage(this.state.previous);
|
||||
|
||||
this.last = () => {
|
||||
const params = merge({}, this.state.params);
|
||||
|
||||
delete params.page;
|
||||
delete params.order_by;
|
||||
|
||||
params.page = 1;
|
||||
params.order_by = '-start_line';
|
||||
|
||||
const promise = $http.get(this.endpoint, { params })
|
||||
.then(({ data }) => {
|
||||
const { results, count } = data;
|
||||
const lastPage = this.getLastPage(count);
|
||||
|
||||
results.reverse();
|
||||
const shifted = results.splice(count % PAGE_SIZE);
|
||||
|
||||
this.state.results = shifted;
|
||||
this.state.count = count;
|
||||
this.state.page = lastPage;
|
||||
this.state.next = lastPage;
|
||||
this.state.last = lastPage;
|
||||
this.state.previous = Math.max(1, this.state.page - 1);
|
||||
|
||||
return { results: shifted, page: lastPage };
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
JobEventsApiService.$inject = [
|
||||
'$http',
|
||||
'$q'
|
||||
];
|
||||
|
||||
export default JobEventsApiService;
|
@ -7,7 +7,6 @@ let resource;
|
||||
let scroll;
|
||||
let engine;
|
||||
let status;
|
||||
let $http;
|
||||
|
||||
let vm;
|
||||
let streaming;
|
||||
@ -23,7 +22,6 @@ function JobsIndexController (
|
||||
_$compile_,
|
||||
_$q_,
|
||||
_status_,
|
||||
_$http_,
|
||||
) {
|
||||
vm = this || {};
|
||||
|
||||
@ -37,7 +35,6 @@ function JobsIndexController (
|
||||
render = _render_;
|
||||
engine = _engine_;
|
||||
status = _status_;
|
||||
$http = _$http_;
|
||||
|
||||
// Development helper(s)
|
||||
vm.clear = devClear;
|
||||
@ -128,37 +125,20 @@ function handleJobEvent (data) {
|
||||
}
|
||||
|
||||
function attachToRunningJob () {
|
||||
const target = `${resource.model.get('url')}${resource.related}/`;
|
||||
const params = { order_by: '-created', page_size: resource.page.size };
|
||||
if (!status.state.running) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
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 page.last()
|
||||
.then(events => {
|
||||
if (!events) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
return append(results);
|
||||
})
|
||||
.then(() => {
|
||||
scroll.setScrollPosition(scroll.getScrollHeight());
|
||||
scroll.resume();
|
||||
const minLine = 1 + Math.max(...events.map(event => event.end_line));
|
||||
|
||||
return $q.resolve();
|
||||
return render.clear()
|
||||
.then(() => engine.setMinLine(minLine));
|
||||
});
|
||||
}
|
||||
|
||||
@ -293,11 +273,11 @@ function scrollEnd () {
|
||||
}
|
||||
|
||||
return render.clear()
|
||||
.then(() => append(events))
|
||||
.then(() => {
|
||||
scroll.setScrollPosition(scroll.getScrollHeight());
|
||||
scroll.resume();
|
||||
});
|
||||
.then(() => append(events));
|
||||
})
|
||||
.then(() => {
|
||||
scroll.setScrollPosition(scroll.getScrollHeight());
|
||||
scroll.resume();
|
||||
});
|
||||
}
|
||||
|
||||
@ -379,7 +359,6 @@ JobsIndexController.$inject = [
|
||||
'$compile',
|
||||
'$q',
|
||||
'JobStatusService',
|
||||
'$http',
|
||||
];
|
||||
|
||||
module.exports = JobsIndexController;
|
||||
|
@ -9,6 +9,7 @@ import ScrollService from '~features/output/scroll.service';
|
||||
import EngineService from '~features/output/engine.service';
|
||||
import StatusService from '~features/output/status.service';
|
||||
import MessageService from '~features/output/message.service';
|
||||
import EventsApiService from '~features/output/api.events.service';
|
||||
import LegacyRedirect from '~features/output/legacy.route';
|
||||
|
||||
import DetailsComponent from '~features/output/details.component';
|
||||
@ -35,7 +36,8 @@ function resolveResource (
|
||||
InventoryUpdate,
|
||||
$stateParams,
|
||||
qs,
|
||||
Wait
|
||||
Wait,
|
||||
eventsApi,
|
||||
) {
|
||||
const { id, type, handleErrors } = $stateParams;
|
||||
const { job_event_search } = $stateParams; // eslint-disable-line camelcase
|
||||
@ -86,23 +88,29 @@ function resolveResource (
|
||||
Object.assign(config.params, query);
|
||||
}
|
||||
|
||||
let model;
|
||||
|
||||
Wait('start');
|
||||
const resourcePromise = new Resource(['get', 'options'], [id, id])
|
||||
.then(model => {
|
||||
const promises = [model.getStats()];
|
||||
.then(job => {
|
||||
const endpoint = `${job.get('url')}${related}/`;
|
||||
eventsApi.init(endpoint, config.params);
|
||||
|
||||
if (model.has('related.labels')) {
|
||||
promises.push(model.extend('get', 'labels'));
|
||||
const promises = [job.getStats(), eventsApi.fetch()];
|
||||
|
||||
if (job.has('related.labels')) {
|
||||
promises.push(job.extend('get', 'labels'));
|
||||
}
|
||||
|
||||
promises.push(model.extend('get', related, config));
|
||||
model = job;
|
||||
return Promise.all(promises);
|
||||
})
|
||||
.then(([stats, model]) => ({
|
||||
.then(([stats, events]) => ({
|
||||
id,
|
||||
type,
|
||||
stats,
|
||||
model,
|
||||
events,
|
||||
related,
|
||||
ws: {
|
||||
events: `${WS_PREFIX}-${key}-${id}`,
|
||||
@ -217,6 +225,7 @@ function JobsRun ($stateRegistry, strings) {
|
||||
'$stateParams',
|
||||
'QuerySet',
|
||||
'Wait',
|
||||
'JobEventsApiService',
|
||||
resolveResource
|
||||
],
|
||||
breadcrumbLabel: [
|
||||
@ -246,6 +255,7 @@ angular
|
||||
.service('JobEventEngine', EngineService)
|
||||
.service('JobStatusService', StatusService)
|
||||
.service('JobMessageService', MessageService)
|
||||
.service('JobEventsApiService', EventsApiService)
|
||||
.component('atJobSearch', SearchComponent)
|
||||
.component('atJobStats', StatsComponent)
|
||||
.component('atJobDetails', DetailsComponent)
|
||||
|
@ -1,6 +1,7 @@
|
||||
function JobPageService ($q) {
|
||||
this.init = ({ resource }) => {
|
||||
this.resource = resource;
|
||||
this.api = this.resource.events;
|
||||
|
||||
this.page = {
|
||||
limit: this.resource.page.pageLimit,
|
||||
@ -125,8 +126,9 @@ function JobPageService ($q) {
|
||||
number = number || reference.state.current;
|
||||
|
||||
reference.state.first = number;
|
||||
reference.state.last = number;
|
||||
reference.state.current = number;
|
||||
reference.state.last = number;
|
||||
|
||||
reference.cache.splice(0, reference.cache.length);
|
||||
};
|
||||
|
||||
@ -203,9 +205,9 @@ function JobPageService ($q) {
|
||||
|
||||
this.next = () => {
|
||||
const reference = this.getActiveReference();
|
||||
const config = this.buildRequestConfig(reference.state.last + 1);
|
||||
const number = reference.state.last + 1;
|
||||
|
||||
return this.resource.model.goToPage(config)
|
||||
return this.api.getPage(number)
|
||||
.then(data => {
|
||||
if (!data || !data.results) {
|
||||
return $q.resolve();
|
||||
@ -219,9 +221,8 @@ function JobPageService ($q) {
|
||||
|
||||
this.previous = () => {
|
||||
const reference = this.getActiveReference();
|
||||
const config = this.buildRequestConfig(reference.state.first - 1);
|
||||
|
||||
return this.resource.model.goToPage(config)
|
||||
return this.api.getPage(reference.state.first - 1)
|
||||
.then(data => {
|
||||
if (!data || !data.results) {
|
||||
return $q.resolve();
|
||||
@ -233,45 +234,29 @@ function JobPageService ($q) {
|
||||
});
|
||||
};
|
||||
|
||||
this.last = () => {
|
||||
const config = this.buildRequestConfig('last');
|
||||
this.last = () => this.api.last()
|
||||
.then(data => {
|
||||
if (!data || !data.results || !data.results.length > 0) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
return this.resource.model.goToPage(config)
|
||||
.then(data => {
|
||||
if (!data || !data.results) {
|
||||
return $q.resolve();
|
||||
}
|
||||
this.emptyCache(data.page);
|
||||
this.addPage(data.page, [], true);
|
||||
|
||||
this.emptyCache(data.page);
|
||||
this.addPage(data.page, [], true);
|
||||
return data.results;
|
||||
});
|
||||
|
||||
return data.results;
|
||||
});
|
||||
};
|
||||
this.first = () => this.api.first()
|
||||
.then(data => {
|
||||
if (!data || !data.results) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
this.first = () => {
|
||||
const config = this.buildRequestConfig('first');
|
||||
this.emptyCache(data.page);
|
||||
this.addPage(data.page, [], false);
|
||||
|
||||
return this.resource.model.goToPage(config)
|
||||
.then(data => {
|
||||
if (!data || !data.results) {
|
||||
return $q.resolve();
|
||||
}
|
||||
|
||||
this.emptyCache(data.page);
|
||||
this.addPage(data.page, [], false);
|
||||
|
||||
return data.results;
|
||||
});
|
||||
};
|
||||
|
||||
this.buildRequestConfig = number => ({
|
||||
page: number,
|
||||
related: this.resource.related,
|
||||
params: {
|
||||
order_by: 'start_line'
|
||||
}
|
||||
});
|
||||
return data.results;
|
||||
});
|
||||
|
||||
this.getActiveReference = () => (this.isBookmarkSet() ?
|
||||
this.getReference(true) : this.getReference());
|
||||
|
Loading…
Reference in New Issue
Block a user