Batch mget requests on dashboard load and cache field_stat results (#10081)

* defer loading visualization saved objects so they can be loaded in a single _mget

* Don't request field stats more than once for the same index pattern

* [ui/courier] batch fetch requests for all searches and docs

* [ui/courier] remove remaining mentions of req.isFetchRequested()

* [courier/fetch/request] remove unneceessary !!
This commit is contained in:
Stacey Gammon 2017-02-09 15:49:12 -05:00 committed by Spencer
parent 0d9e51f72f
commit f2da2a3640
3 changed files with 58 additions and 13 deletions

View file

@ -8,23 +8,32 @@ import ReqStatusProvider from './req_status';
export default function fetchService(Private, Promise) {
const requestQueue = Private(RequestQueueProvider);
const fetchThese = Private(FetchTheseProvider);
const immediatelyFetchThese = Private(FetchTheseProvider);
const callResponseHandlers = Private(CallResponseHandlersProvider);
const INCOMPLETE = Private(ReqStatusProvider).INCOMPLETE;
function fetchQueued(strategy) {
const requests = requestQueue.getStartable(strategy);
if (!requests.length) return Promise.resolve();
else return fetchThese(requests);
}
const debouncedFetchThese = _.debounce(() => {
const requests = requestQueue.get().filter(req => req.isFetchRequestedAndPending());
immediatelyFetchThese(requests);
}, {
wait: 10,
maxWait: 50
});
this.fetchQueued = fetchQueued;
const fetchTheseSoon = (requests) => {
requests.forEach(req => req._setFetchRequested());
debouncedFetchThese();
return Promise.all(requests.map(req => req.defer.promise));
};
this.fetchQueued = (strategy) => {
return fetchTheseSoon(requestQueue.getStartable(strategy));
};
function fetchASource(source, strategy) {
const defer = Promise.defer();
fetchThese([
fetchTheseSoon([
source._createRequest(defer)
]);
@ -50,7 +59,7 @@ export default function fetchService(Private, Promise) {
* @param {array} reqs - the requests to fetch
* @async
*/
this.these = fetchThese;
this.these = fetchTheseSoon;
/**
* Send responses to a list of requests, used when requests

View file

@ -15,12 +15,42 @@ export default function AbstractReqProvider(Private, Promise) {
this.source = source;
this.defer = defer || Promise.defer();
this._whenAbortedHandlers = [];
requestQueue.push(this);
}
/**
* Called by the loopers to find requests that should be sent to the
* fetch() module. When a module is sent to fetch() it's _fetchRequested flag
* is set, and this consults that flag so requests are not send to fetch()
* multiple times.
*
* @return {Boolean}
*/
canStart() {
return Boolean(!this.stopped && !this.source._fetchDisabled);
return !this._fetchRequested && !this.stopped && !this.source._fetchDisabled;
}
/**
* Used to find requests that were previously sent to the fetch() module but
* have not been started yet, so they can be started.
*
* @return {Boolean}
*/
isFetchRequestedAndPending() {
return this._fetchRequested && !this.started;
}
/**
* Called by the fetch() module when this request has been sent to
* be fetched. At that point the request is somewhere between `ready-to-start`
* and `started`. The fetch module then waits a short period of time to
* allow requests to build up in the request queue, and then immediately
* fetches all requests that return true from `isFetchRequestedAndPending()`
*
* @return {undefined}
*/
_setFetchRequested() {
this._fetchRequested = true;
}
start() {

View file

@ -15,6 +15,8 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter, kbn
* @return {Promise} - a promise that is fulfilled by the request body
*/
reqsFetchParamsToBody: function (reqsFetchParams) {
const indexToListMapping = {};
return Promise.map(reqsFetchParams, function (fetchParams) {
return Promise.resolve(fetchParams.index)
.then(function (indexList) {
@ -23,7 +25,11 @@ export default function FetchStrategyForSearch(Private, Promise, timefilter, kbn
}
const timeBounds = timefilter.getBounds();
return indexList.toIndexList(timeBounds.min, timeBounds.max);
if (!indexToListMapping[indexList.id]) {
indexToListMapping[indexList.id] = indexList.toIndexList(timeBounds.min, timeBounds.max);
}
return indexToListMapping[indexList.id];
})
.then(function (indexList) {
let body = fetchParams.body || {};