Skip to content

Commit

Permalink
Batch mget requests on dashboard load and cache field_stat results (#…
Browse files Browse the repository at this point in the history
…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 !!
  • Loading branch information
stacey-gammon authored and spalger committed Feb 9, 2017
1 parent 0d9e51f commit f2da2a3
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 13 deletions.
29 changes: 19 additions & 10 deletions src/ui/public/courier/fetch/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
]);

Expand All @@ -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
Expand Down
34 changes: 32 additions & 2 deletions src/ui/public/courier/fetch/request/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
8 changes: 7 additions & 1 deletion src/ui/public/courier/fetch/strategy/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 || {};
Expand Down

0 comments on commit f2da2a3

Please sign in to comment.