@spalger/kibana
Version:
Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic
120 lines (99 loc) • 3.61 kB
JavaScript
define(function (require) {
return function CourierFetchCallClient(Private, Promise, es, esShardTimeout, sessionId) {
var _ = require('lodash');
var isRequest = Private(require('ui/courier/fetch/_is_request'));
var mergeDuplicateRequests = Private(require('ui/courier/fetch/_merge_duplicate_requests'));
var ABORTED = Private(require('ui/courier/fetch/_req_status')).ABORTED;
var DUPLICATE = Private(require('ui/courier/fetch/_req_status')).DUPLICATE;
function callClient(strategy, requests) {
// merging docs can change status to DUPLICATE, capture new statuses
var statuses = mergeDuplicateRequests(requests);
// get the actual list of requests that we will be fetching
var executable = statuses.filter(isRequest);
var execCount = executable.length;
// resolved by respond()
var esPromise;
var defer = Promise.defer();
// for each respond with either the response or ABORTED
var respond = function (responses) {
responses = responses || [];
return Promise.map(requests, function (req, i) {
switch (statuses[i]) {
case ABORTED:
return ABORTED;
case DUPLICATE:
return req._uniq.resp;
default:
return responses[_.findIndex(executable, req)];
}
})
.then(defer.resolve, defer.reject);
};
// handle a request being aborted while being fetched
var requestWasAborted = Promise.method(function (req, i) {
if (statuses[i] === ABORTED) {
defer.reject(new Error('Request was aborted twice?'));
}
execCount -= 1;
if (execCount > 0) {
// the multi-request still contains other requests
return;
}
if (esPromise && _.isFunction(esPromise.abort)) {
esPromise.abort();
}
esPromise = ABORTED;
return respond();
});
// attach abort handlers, close over request index
statuses.forEach(function (req, i) {
if (!isRequest(req)) return;
req.whenAborted(function () {
requestWasAborted(req, i).catch(defer.reject);
});
});
// Now that all of THAT^^^ is out of the way, lets actually
// call out to elasticsearch
Promise.map(executable, function (req) {
return Promise.try(req.getFetchParams, void 0, req)
.then(function (fetchParams) {
return (req.fetchParams = fetchParams);
});
})
.then(function (reqsFetchParams) {
return strategy.reqsFetchParamsToBody(reqsFetchParams);
})
.then(function (body) {
// while the strategy was converting, our request was aborted
if (esPromise === ABORTED) {
throw ABORTED;
}
return (esPromise = es[strategy.clientMethod]({
timeout: esShardTimeout,
ignore_unavailable: true,
preference: sessionId,
body: body
}));
})
.then(function (clientResp) {
return strategy.getResponses(clientResp);
})
.then(respond)
.catch(function (err) {
if (err === ABORTED) respond();
else defer.reject(err);
});
// return our promise, but catch any errors we create and
// send them to the requests
return defer.promise
.catch(function (err) {
requests.forEach(function (req, i) {
if (statuses[i] !== ABORTED) {
req.handleFailure(err);
}
});
});
}
return callClient;
};
});