From a84884050161044b39843110daf5011ea960f0d4 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 27 Mar 2019 14:14:01 -0700 Subject: [PATCH] Remove segmented fetch (#33453) * Remove segmented fetch * Fix namespace * Remove unused translations --- docs/management/advanced-options.asciidoc | 3 - .../public/discover/__tests__/hit_sort_fn.js | 93 ----- .../kibana/public/discover/_hit_sort_fn.js | 82 ----- .../public/discover/controllers/discover.js | 240 ++++-------- .../kibana/public/discover/index.html | 2 - .../kibana/ui_setting_defaults.js | 13 - .../segmented_search_request.create_queue.js | 82 ----- ...egmented_search_request.index_selection.js | 148 -------- .../__tests__/segmented_search_request.js | 88 ----- .../segmented_search_request.size_picking.js | 70 ---- .../request/segmented_search_request/index.js | 20 - .../segmented_handle.js | 59 --- .../segmented_search_request.js | 346 ------------------ .../courier/search_source/search_source.js | 22 -- .../translations/translations/zh-CN.json | 6 +- 15 files changed, 70 insertions(+), 1204 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js delete mode 100644 src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js delete mode 100644 src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 78b6922927c1..50a229f0b2dd 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -41,9 +41,6 @@ working on big documents. Set this property to `false` to disable highlighting. `doc_table:hideTimeColumn`:: Hide the 'Time' column in Discover and in all Saved Searches on Dashboards. `search:includeFrozen`:: Will include {ref}/frozen-indices.html[frozen indices] in results if enabled. Searching through frozen indices might increase the search time. -`courier:maxSegmentCount`:: Kibana splits requests in the Discover app into segments to limit the size of requests sent to -the Elasticsearch cluster. This setting constrains the length of the segment list. Long segment lists can significantly -increase request processing time. `courier:ignoreFilterIfFieldNotInIndex`:: Set this property to `true` to skip filters that apply to fields that don't exist in a visualization's index. Useful when dashboards consist of visualizations from multiple index patterns. `courier:maxConcurrentShardRequests`:: Controls the {ref}/search-multi-search.html[max_concurrent_shard_requests] setting used for _msearch requests sent by Kibana. Set to 0 to disable this config and use the Elasticsearch default. `fields:popularLimit`:: This setting governs how many of the top most popular fields are shown. diff --git a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js deleted file mode 100644 index 3c7e1e83688d..000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/__tests__/hit_sort_fn.js +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -import _ from 'lodash'; -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; - -describe('hit sort function', function () { - let createHitSortFn; - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject(function (Private) { - createHitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider); - })); - - - const runSortTest = function (dir, sortOpts) { - const groupSize = _.random(10, 30); - const total = sortOpts.length * groupSize; - - sortOpts = sortOpts.map(function (opt) { - if (Array.isArray(opt)) return opt; - else return [opt]; - }); - const sortOptLength = sortOpts.length; - - const hits = _.times(total, function (i) { - return { - _source: {}, - sort: sortOpts[i % sortOptLength] - }; - }); - - hits.sort(createHitSortFn(dir)) - .forEach(function (hit, i) { - const group = Math.floor(i / groupSize); - expect(hit.sort).to.eql(sortOpts[group]); - }); - }; - - - it('sorts a list of hits in ascending order', function () { - runSortTest('asc', [200, 404, 500]); - }); - - it('sorts a list of hits in descending order', function () { - runSortTest('desc', [10, 3, 1]); - }); - - it('breaks ties in ascending order', function () { - runSortTest('asc', [ - [ 'apache', 200, 'facebook.com' ], - [ 'apache', 200, 'twitter.com' ], - [ 'apache', 301, 'facebook.com' ], - [ 'apache', 301, 'twitter.com' ], - [ 'nginx', 200, 'facebook.com' ], - [ 'nginx', 200, 'twitter.com' ], - [ 'nginx', 301, 'facebook.com' ], - [ 'nginx', 301, 'twitter.com' ] - ]); - }); - - it('breaks ties in descending order', function () { - runSortTest('desc', [ - [ 'nginx', 301, 'twitter.com' ], - [ 'nginx', 301, 'facebook.com' ], - [ 'nginx', 200, 'twitter.com' ], - [ 'nginx', 200, 'facebook.com' ], - [ 'apache', 301, 'twitter.com' ], - [ 'apache', 301, 'facebook.com' ], - [ 'apache', 200, 'twitter.com' ], - [ 'apache', 200, 'facebook.com' ] - ]); - }); -}); diff --git a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js b/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js deleted file mode 100644 index c60f13bb76d4..000000000000 --- a/src/legacy/core_plugins/kibana/public/discover/_hit_sort_fn.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// eslint-disable-next-line @kbn/eslint/no-default-export -export default function HitSortFnFactory() { - /** - * Creates a sort function that will resort hits based on the value - * es used to sort them. - * - * background: - * When a hit is sorted by elasticsearch, es will write the values that it used - * to sort them into an array at the top level of the hit like so - * - * ``` - * hits: { - * total: x, - * hits: [ - * { - * _id: i, - * _source: {}, - * sort: [ - * // all values used to sort, in the order of precedence - * ] - * } - * ] - * }; - * ``` - * - * @param {[type]} field [description] - * @param {[type]} direction [description] - * @return {[type]} [description] - */ - return function createHitSortFn(direction) { - const descending = (direction === 'desc'); - - return function sortHits(hitA, hitB) { - let bBelowa = null; - - const aSorts = hitA.sort || []; - const bSorts = hitB.sort || []; - - // walk each sort value, and compare until one is different - for (let i = 0; i < bSorts.length; i++) { - const a = aSorts[i]; - const b = bSorts[i]; - - if (a == null || b > a) { - bBelowa = !descending; - break; - } - - if (b < a) { - bBelowa = descending; - break; - } - } - - if (bBelowa !== null) { - return bBelowa ? -1 : 1; - } else { - return 0; - } - - }; - }; -} diff --git a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js index 3c8da5dd3ab8..2eba42eded54 100644 --- a/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/controllers/discover.js @@ -39,7 +39,6 @@ import { toastNotifications } from 'ui/notify'; import { VisProvider } from 'ui/vis'; import { VislibSeriesResponseHandlerProvider } from 'ui/vis/response_handlers/vislib'; import { DocTitleProvider } from 'ui/doc_title'; -import PluginsKibanaDiscoverHitSortFnProvider from '../_hit_sort_fn'; import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter'; import { intervalOptions } from 'ui/agg_types/buckets/_interval_options'; import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory'; @@ -67,6 +66,12 @@ import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_s import { getRootBreadcrumbs, getSavedSearchBreadcrumbs } from '../breadcrumbs'; import { buildVislibDimensions } from 'ui/visualize/loader/pipeline_helpers/build_pipeline'; +const fetchStatuses = { + UNINITIALIZED: 'uninitialized', + LOADING: 'loading', + COMPLETE: 'complete', +}; + const app = uiModules.get('apps/discover', [ 'kibana/notify', 'kibana/courier', @@ -170,7 +175,6 @@ function discoverController( let visualizeHandler; const Vis = Private(VisProvider); const docTitle = Private(DocTitleProvider); - const HitSortFn = Private(PluginsKibanaDiscoverHitSortFnProvider); const queryFilter = Private(FilterBarQueryFilterProvider); const responseHandler = Private(VislibSeriesResponseHandlerProvider).handler; const filterManager = Private(FilterManagerProvider); @@ -190,6 +194,7 @@ function discoverController( $scope.intervalOptions = intervalOptions; $scope.showInterval = false; $scope.minimumVisibleRows = 50; + $scope.fetchStatus = fetchStatuses.UNINITIALIZED; $scope.intervalEnabled = function (interval) { return interval.val !== 'custom'; @@ -373,18 +378,16 @@ function discoverController( const getFieldCounts = async () => { // the field counts aren't set until we have the data back, // so we wait for the fetch to be done before proceeding - if (!$scope.fetchStatus) { + if ($scope.fetchStatus === fetchStatuses.COMPLETE) { return $scope.fieldCounts; } return await new Promise(resolve => { const unwatch = $scope.$watch('fetchStatus', (newValue) => { - if (newValue) { - return; + if (newValue === fetchStatuses.COMPLETE) { + unwatch(); + resolve($scope.fieldCounts); } - - unwatch(); - resolve($scope.fieldCounts); }); }); }; @@ -567,13 +570,9 @@ function discoverController( if (rows == null && oldRows == null) return status.LOADING; const rowsEmpty = _.isEmpty(rows); - // An undefined fetchStatus means the requests are still being - // prepared to be sent. When all requests are completed, - // fetchStatus is set to null, so it's important that we - // specifically check for undefined to determine a loading status. - const preparingForFetch = _.isUndefined(fetchStatus); + const preparingForFetch = fetchStatus === fetchStatuses.UNINITIALIZED; if (preparingForFetch) return status.LOADING; - else if (rowsEmpty && fetchStatus) return status.LOADING; + else if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING; else if (!rowsEmpty) return status.READY; else return status.NO_RESULTS; } @@ -662,6 +661,8 @@ function discoverController( .then(setupVisualization) .then(function () { $state.save(); + $scope.fetchStatus = fetchStatuses.LOADING; + logInspectorRequest(); return courier.fetch(); }) .catch(notify.error); @@ -673,176 +674,72 @@ function discoverController( $scope.fetch(); }; + function onResults(resp) { + logInspectorResponse(resp); - function handleSegmentedFetch(segmented) { - function flushResponseData() { - $scope.fetchError = undefined; - $scope.hits = 0; - $scope.failures = []; - $scope.rows = []; - $scope.fieldCounts = {}; - } - - if (!$scope.rows) flushResponseData(); - - const sort = $state.sort; - const timeField = $scope.indexPattern.timeFieldName; - - /** - * Basically an emum. - * - * opts: - * "time" - sorted by the timefield - * "non-time" - explicitly sorted by a non-time field, NOT THE SAME AS `sortBy !== "time"` - * "implicit" - no sorting set, NOT THE SAME AS "non-time" - * - * @type {String} - */ - const sortBy = (function () { - if (!Array.isArray(sort)) return 'implicit'; - else if (sort[0] === '_score') return 'implicit'; - else if (sort[0] === timeField) return 'time'; - else return 'non-time'; - }()); - - let sortFn = null; - if (sortBy !== 'implicit') { - sortFn = new HitSortFn(sort[1]); - } - - $scope.updateTime(); - - if (sort[0] === '_score') { - segmented.setMaxSegments(1); - } - - segmented.setDirection(sortBy === 'time' ? (sort[1] || 'desc') : 'desc'); - segmented.setSortFn(sortFn); - segmented.setSize($scope.opts.sampleSize); - - let inspectorRequests = []; - function logResponseInInspector(resp) { - if (inspectorRequests.length > 0) { - const inspectorRequest = inspectorRequests.shift(); - inspectorRequest - .stats(getResponseInspectorStats($scope.searchSource, resp)) - .ok({ json: resp }); - } - } - - // triggered when the status updated - segmented.on('status', function (status) { - $scope.fetchStatus = status; - if (status.complete === 0) { - // starting new segmented search request - inspectorAdapters.requests.reset(); - inspectorRequests = []; - } - - if (status.remaining > 0) { - const inspectorRequest = inspectorAdapters.requests.start( - i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle', { - defaultMessage: 'Segment {fetchCompleteStatus}', - values: { - fetchCompleteStatus: $scope.fetchStatus.complete, + if ($scope.opts.timefield) { + const tabifiedData = tabifyAggResponse($scope.vis.aggs, resp); + $scope.searchSource.rawResponse = resp; + Promise + .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource })) + .then(resp => responseHandler(tabifiedData, resp)) + .then(resp => { + visualizeHandler.render({ + as: 'visualization', + value: { + visType: $scope.vis.type.name, + visData: resp, + visConfig: $scope.vis.params, + params: {}, } - }), - { - description: i18n('kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription', { - defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.', - }), }); - inspectorRequest.stats(getRequestInspectorStats($scope.searchSource)); - $scope.searchSource.getSearchRequestBody().then(body => { - inspectorRequest.json(body); }); - inspectorRequests.push(inspectorRequest); - } + } - }); + $scope.hits = resp.hits.total; + $scope.rows = resp.hits.hits; - segmented.on('first', function () { - flushResponseData(); - }); + // if we haven't counted yet, reset the counts + const counts = $scope.fieldCounts = $scope.fieldCounts || {}; - segmented.on('segment', (resp) => { - logResponseInInspector(resp); - if (resp._shards.failed > 0) { - $scope.failures = _.union($scope.failures, resp._shards.failures); - $scope.failures = _.uniq($scope.failures, false, function (failure) { - return failure.index + failure.shard + failure.reason; - }); - } - }); - - segmented.on('emptySegment', function (resp) { - logResponseInInspector(resp); - }); - - segmented.on('mergedSegment', function (merged) { - $scope.mergedEsResp = merged; - - if ($scope.opts.timefield) { - const tabifiedData = tabifyAggResponse($scope.vis.aggs, merged); - $scope.searchSource.rawResponse = merged; - Promise - .resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource })) - .then(resp => responseHandler(tabifiedData, resp)) - .then(resp => { - visualizeHandler.render({ - as: 'visualization', - value: { - visType: $scope.vis.type.name, - visData: resp, - visConfig: $scope.vis.params, - params: {}, - } - }); - }); - } - - $scope.hits = merged.hits.total; - - const indexPattern = $scope.searchSource.getField('index'); - - // the merge rows, use a new array to help watchers - $scope.rows = merged.hits.hits.slice(); - - let counts = $scope.fieldCounts; - - // if we haven't counted yet, or need a fresh count because we are sorting, reset the counts - if (!counts || sortFn) counts = $scope.fieldCounts = {}; - - $scope.rows.forEach(function (hit) { - // skip this work if we have already done it - if (hit.$$_counted) return; - - // when we are sorting results, we need to redo the counts each time because the - // "top 500" may change with each response, so don't mark this as counted - if (!sortFn) hit.$$_counted = true; - - const fields = _.keys(indexPattern.flattenHit(hit)); - let n = fields.length; - let field; - while (field = fields[--n]) { - if (counts[field]) counts[field] += 1; - else counts[field] = 1; - } + $scope.rows.forEach(hit => { + const fields = Object.keys($scope.indexPattern.flattenHit(hit)); + fields.forEach(fieldName => { + counts[fieldName] = (counts[fieldName] || 0) + 1; }); }); - segmented.on('complete', function () { - if ($scope.fetchStatus.hitCount === 0) { - flushResponseData(); - } + $scope.fetchStatus = fetchStatuses.COMPLETE; - $scope.fetchStatus = null; + return $scope.searchSource.onResults().then(onResults); + } + + let inspectorRequest; + + function logInspectorRequest() { + inspectorAdapters.requests.reset(); + const title = i18n('kbn.discover.inspectorRequestDataTitle', { + defaultMessage: 'Data', + }); + const description = i18n('kbn.discover.inspectorRequestDescription', { + defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.', + }); + inspectorRequest = inspectorAdapters.requests.start(title, { description }); + inspectorRequest.stats(getRequestInspectorStats($scope.searchSource)); + $scope.searchSource.getSearchRequestBody().then(body => { + inspectorRequest.json(body); }); } + function logInspectorResponse(resp) { + inspectorRequest + .stats(getResponseInspectorStats($scope.searchSource, resp)) + .ok({ json: resp }); + } - function beginSegmentedFetch() { - $scope.searchSource.onBeginSegmentedFetch(handleSegmentedFetch) + function startSearching() { + return $scope.searchSource.onResults() + .then(onResults) .catch((error) => { const fetchError = getPainlessError(error); @@ -853,10 +750,11 @@ function discoverController( } // Restart. This enables auto-refresh functionality. - beginSegmentedFetch(); + startSearching(); }); } - beginSegmentedFetch(); + + startSearching(); $scope.updateTime = function () { $scope.timeRange = { diff --git a/src/legacy/core_plugins/kibana/public/discover/index.html b/src/legacy/core_plugins/kibana/public/discover/index.html index ecd6dcf5e677..4def63c620d4 100644 --- a/src/legacy/core_plugins/kibana/public/discover/index.html +++ b/src/legacy/core_plugins/kibana/public/discover/index.html @@ -101,8 +101,6 @@ >
-
-
{{fetchStatus.complete}} / {{fetchStatus.total}}
diff --git a/src/legacy/core_plugins/kibana/ui_setting_defaults.js b/src/legacy/core_plugins/kibana/ui_setting_defaults.js index 55cdc3e38e7f..00af1aeae26b 100644 --- a/src/legacy/core_plugins/kibana/ui_setting_defaults.js +++ b/src/legacy/core_plugins/kibana/ui_setting_defaults.js @@ -302,19 +302,6 @@ export function getUiSettingDefaults() { }), category: ['discover'], }, - 'courier:maxSegmentCount': { - name: i18n.translate('kbn.advancedSettings.courier.maxSegmentCountTitle', { - defaultMessage: 'Maximum segment count', - }), - value: 30, - description: i18n.translate('kbn.advancedSettings.courier.maxSegmentCountText', { - defaultMessage: - 'Requests in discover are split into segments to prevent massive requests from being sent to elasticsearch. ' + - 'This setting attempts to prevent the list of segments from getting too long, ' + - 'which might cause requests to take much longer to process.', - }), - category: ['search'], - }, 'courier:ignoreFilterIfFieldNotInIndex': { name: i18n.translate('kbn.advancedSettings.courier.ignoreFilterTitle', { defaultMessage: 'Ignore filter(s)', diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js deleted file mode 100644 index 80f0ce3309a4..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.create_queue.js +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest _createQueue', () => { - let Promise; - let SegmentedSearchRequest; - let MockSource; - - require('test_utils/no_digest_promises').activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - it('manages the req._queueCreated flag', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._queueCreated = null; - - const promise = req._createQueue(); - expect(req._queueCreated).to.be(false); - await promise; - expect(req._queueCreated).to.be(true); - }); - - it('relies on indexPattern.toDetailedIndexList to generate queue', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - const indices = [1, 2, 3]; - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve(indices)); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - const output = await req._createQueue(); - expect(output).to.equal(indices); - }); - - it('tells the index pattern its direction', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([1, 2, 3])); - - req.setDirection('asc'); - await req._createQueue(); - expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('asc'); - - req.setDirection('desc'); - await req._createQueue(); - expect(indexPattern.toDetailedIndexList.lastCall.args[2]).to.be('desc'); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js deleted file mode 100644 index 6914e9338028..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.index_selection.js +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; -import { times } from 'lodash'; -import sinon from 'sinon'; - -import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn'; -import NoDigestPromises from 'test_utils/no_digest_promises'; -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest index selection', function () { - let Promise; - let SegmentedSearchRequest; - let MockSource; - let HitSortFn; - - NoDigestPromises.activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - HitSortFn = Private(HitSortFnProv); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - it('queries with size until all 500 docs returned', async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([ - { index: 'one', min: 0, max: 1 }, - { index: 'two', min: 0, max: 1 }, - { index: 'three', min: 0, max: 1 }, - { index: 'four', min: 0, max: 1 }, - { index: 'five', min: 0, max: 1 }, - ])); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - req._handle.setSize(500); - await req.start(); - - // first 200 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - // total = 400 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - // total = 600 - expect((await req.getFetchParams()).body.size).to.be(500); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: times(200, (i) => ({ i })) } - }); - }); - - it(`sets size 0 for indices that couldn't preclude hits`, async function () { - const searchSource = new MockSource(); - const indexPattern = searchSource.getField('index'); - - // the segreq is looking for 10 documents, and we will give it ten docs with time:5 in the first response. - // on the second index it should still request 10 documents because it could produce documents with time:5. - // the next two indexes will get size 0, since they couldn't produce documents with the time:5 - // the final index will get size:10, because it too can produce docs with time:5 - sinon.stub(indexPattern, 'toDetailedIndexList').returns(Promise.resolve([ - { index: 'one', min: 0, max: 10 }, - { index: 'two', min: 0, max: 10 }, - { index: 'three', min: 12, max: 20 }, - { index: 'four', min: 15, max: 20 }, - { index: 'five', min: 5, max: 50 }, - ])); - - const req = new SegmentedSearchRequest({ source: searchSource, errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - req._handle.setSize(10); - await req.start(); - - // first 10 - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - - // total = 400 - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - - // total = 600 - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: [] } - }); - - expect((await req.getFetchParams()).body.size).to.be(0); - await req.handleResponse({ - hits: { total: 1000, hits: [] } - }); - - expect((await req.getFetchParams()).body.size).to.be(10); - await req.handleResponse({ - hits: { total: 1000, hits: times(10, () => ({ _source: { time: 5 } })) } - }); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js deleted file mode 100644 index 33b8140b746f..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import sinon from 'sinon'; -import expect from '@kbn/expect'; -import ngMock from 'ng_mock'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; -import { SearchRequestProvider } from '../../search_request'; - -describe('SegmentedSearchRequest', () => { - let Promise; - let SegmentedSearchRequest; - let segmentedReq; - let abstractReqStart; - - beforeEach(ngMock.module('kibana')); - - beforeEach(ngMock.inject((Private, $injector) => { - Promise = $injector.get('Promise'); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - const SearchRequest = Private(SearchRequestProvider); - abstractReqStart = sinon.stub(SearchRequest.prototype, 'start').callsFake(() => { - const promise = Promise.resolve(); - sinon.spy(promise, 'then'); - return promise; - }); - })); - - describe('#start()', () => { - let returned; - beforeEach(() => { - init(); - returned = segmentedReq.start(); - }); - - it('returns promise', () => { - expect(returned.then).to.be.Function; - }); - - it('calls AbstractReq#start()', () => { - sinon.assert.calledOnce(abstractReqStart); - }); - - it('listens to promise from super.start()', () => { - sinon.assert.calledOnce(abstractReqStart); - const promise = abstractReqStart.firstCall.returnValue; - sinon.assert.calledOnce(promise.then); - }); - }); - - function init() { - segmentedReq = new SegmentedSearchRequest({ source: mockSource(), errorHandler: () => {} }); - } - - function mockSource() { - return { - get: sinon.stub().returns(mockIndexPattern()), - }; - } - - function mockIndexPattern() { - return { - toDetailedIndexList: sinon.stub().returns(Promise.resolve([ - { index: 1, min: 0, max: 1 }, - { index: 2, min: 0, max: 1 }, - { index: 3, min: 0, max: 1 }, - ])) - }; - } -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js deleted file mode 100644 index 7b499fbd87e0..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/__tests__/segmented_search_request.size_picking.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import ngMock from 'ng_mock'; -import expect from '@kbn/expect'; - -import HitSortFnProv from 'plugins/kibana/discover/_hit_sort_fn'; -import NoDigestPromises from 'test_utils/no_digest_promises'; -import StubbedSearchSourceProvider from 'fixtures/stubbed_search_source'; - -import { SegmentedSearchRequestProvider } from '../segmented_search_request'; - -describe('SegmentedSearchRequest size picking', function () { - let SegmentedSearchRequest; - let MockSource; - let HitSortFn; - - NoDigestPromises.activateForSuite(); - - beforeEach(ngMock.module('kibana')); - beforeEach(ngMock.inject((Private, $injector) => { - HitSortFn = Private(HitSortFnProv); - SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); - - MockSource = class { - constructor() { - return $injector.invoke(StubbedSearchSourceProvider); - } - }; - })); - - describe('without a size', function () { - it('does not set the request size', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSortFn(new HitSortFn('desc')); - await req.start(); - - expect((await req.getFetchParams()).body).to.not.have.property('size'); - }); - }); - - describe('with a size', function () { - it('sets the request size to the entire desired size', async function () { - const req = new SegmentedSearchRequest({ source: new MockSource(), errorHandler: () => {} }); - req._handle.setDirection('desc'); - req._handle.setSize(555); - req._handle.setSortFn(new HitSortFn('desc')); - await req.start(); - - expect((await req.getFetchParams()).body).to.have.property('size', 555); - }); - }); -}); diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js deleted file mode 100644 index b10169bd42ee..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/index.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { SegmentedSearchRequestProvider } from './segmented_search_request'; diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js deleted file mode 100644 index b7a638b4ed15..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_handle.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { EventsProvider } from '../../../../events'; - -export function SegmentedHandleProvider(Private) { - const Events = Private(EventsProvider); - - const segmentedRequest = Symbol('Actual Segmented Request'); - - /** - * Simple class for creating an object to send to the - * requester of a SegmentedSearchRequest. Since the SegmentedSearchRequest - * extends AbstractRequest, it wasn't able to be the event - * emitter it was born to be. This provides a channel for - * setting values on the segmented request, and an event - * emitter for the request to speak outwardly - * - * @param {SegmentedSearchRequest} - req - the request this handle relates to - */ - return class SegmentedHandle extends Events { - constructor(req) { - super(); - this[segmentedRequest] = req; - } - - setDirection(...args) { - this[segmentedRequest].setDirection(...args); - } - - setSize(...args) { - this[segmentedRequest].setSize(...args); - } - - setMaxSegments(...args) { - this[segmentedRequest].setMaxSegments(...args); - } - - setSortFn(...args) { - this[segmentedRequest].setSortFn(...args); - } - }; -} diff --git a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js b/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js deleted file mode 100644 index 6ab49eee4fe6..000000000000 --- a/src/legacy/ui/public/courier/fetch/request/segmented_search_request/segmented_search_request.js +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; -import { timefilter } from 'ui/timefilter'; -import { SearchRequestProvider } from '../search_request'; -import { SegmentedHandleProvider } from './segmented_handle'; -import { pushAll } from '../../../../utils/collection'; - -export function SegmentedSearchRequestProvider(Private, config) { - const SearchRequest = Private(SearchRequestProvider); - const SegmentedHandle = Private(SegmentedHandleProvider); - - class SegmentedSearchRequest extends SearchRequest { - constructor({ source, defer, errorHandler, initFn }) { - super({ source, defer, errorHandler }); - - this.type = 'segmented'; - - // segmented request specific state - this._initFn = initFn; - - this._desiredSize = null; - this._maxSegments = config.get('courier:maxSegmentCount'); - this._direction = 'desc'; - this._sortFn = null; - this._queueCreated = false; - this._handle = new SegmentedHandle(this); - - this._hitWindow = null; - - // prevent the source from changing between requests, - // all calls will return the same promise - this._getFlattenedSource = _.once(this._getFlattenedSource); - } - - /********* - ** SearchReq overrides - *********/ - - start() { - return super.start().then(() => { - this._complete = []; - this._active = null; - this._segments = []; - this._all = []; - this._queue = []; - - this._mergedResp = { - took: 0, - hits: { - hits: [], - total: 0, - max_score: 0 - } - }; - - // give the request consumer a chance to receive each segment and set - // parameters via the handle - if (_.isFunction(this._initFn)) this._initFn(this._handle); - return this._createQueue(); - }) - .then((queue) => { - if (this.stopped) return; - - this._all = queue.slice(0); - - // Send the initial fetch status - return this._reportStatus(); - }); - } - - continue() { - return this._reportStatus(); - } - - getFetchParams() { - return this._getFlattenedSource().then(flatSource => { - const params = _.cloneDeep(flatSource); - - // calculate the number of indices to fetch in this request in order to prevent - // more than this._maxSegments requests. We use Math.max(1, n) to ensure that each request - // has at least one index pattern, and Math.floor() to make sure that if the - // number of indices does not round out evenly the extra index is tacked onto the last - // request, making sure the first request returns faster. - const remainingSegments = this._maxSegments - this._segments.length; - const indexCount = Math.max(1, Math.floor(this._queue.length / remainingSegments)); - - const indices = this._active = this._queue.splice(0, indexCount); - params.index = indices.map(({ index }) => index).join(','); - - if (_.isNumber(this._desiredSize)) { - params.body.size = this._pickSizeForIndices(indices); - } - - return params; - }); - } - - handleResponse(resp) { - return this._consumeSegment(resp); - } - - filterError(resp) { - if (/ClusterBlockException.*index\sclosed/.test(resp.error)) { - this._consumeSegment(false); - return true; - } - } - - isIncomplete() { - const queueNotCreated = !this._queueCreated; - const queueNotEmpty = this._queue.length > 0; - return queueNotCreated || queueNotEmpty; - } - - clone() { - return new SegmentedSearchRequest(this.source, this.defer, this._initFn); - } - - complete() { - this._reportStatus(); - this._handle.emit('complete'); - return super.complete(); - } - - /********* - ** SegmentedSearchRequest specific methods - *********/ - - - /** - * Set the sort total number of segments to emit - * - * @param {number} - */ - setMaxSegments(maxSegments) { - this._maxSegments = Math.max(_.parseInt(maxSegments), 1); - } - - /** - * Set the sort direction for the request. - * - * @param {string} dir - one of 'asc' or 'desc' - */ - setDirection(dir) { - switch (dir) { - case 'asc': - case 'desc': - return (this._direction = dir); - default: - throw new TypeError('unknown sort direction "' + dir + '"'); - } - } - - /** - * Set the function that will be used to sort the rows - * - * @param {fn} - */ - setSortFn(sortFn) { - this._sortFn = sortFn; - } - - /** - * Set the sort total number of documents to - * emit - * - * Setting to false will not limit the documents, - * if a number is set the size of the request to es - * will be updated on each new request - * - * @param {number|false} - */ - setSize(totalSize) { - this._desiredSize = _.parseInt(totalSize); - if (isNaN(this._desiredSize)) this._desiredSize = null; - } - - _createQueue() { - const timeBounds = timefilter.getBounds(); - const indexPattern = this.source.getField('index'); - this._queueCreated = false; - - return indexPattern.toDetailedIndexList(timeBounds.min, timeBounds.max, this._direction) - .then(queue => { - this._queue = queue; - this._queueCreated = true; - return queue; - }); - } - - _reportStatus() { - return this._handle.emit('status', { - total: this._queueCreated ? this._all.length : NaN, - complete: this._queueCreated ? this._complete.length : NaN, - remaining: this._queueCreated ? this._queue.length : NaN, - hitCount: this._queueCreated ? this._mergedResp.hits.hits.length : NaN - }); - } - - _getFlattenedSource() { - return this.source._flatten(); - } - - _consumeSegment(seg) { - const index = this._active; - this._complete.push(index); - if (!seg) return; // segment was ignored/filtered, don't store it - - const hadHits = _.get(this._mergedResp, 'hits.hits.length') > 0; - const gotHits = _.get(seg, 'hits.hits.length') > 0; - const firstHits = !hadHits && gotHits; - const haveHits = hadHits || gotHits; - - this._mergeSegment(seg); - this.resp = _.omit(this._mergedResp, '_bucketIndex'); - - if (firstHits) this._handle.emit('first', seg); - gotHits ? this._handle.emit('segment', seg) : this._handle.emit('emptySegment', seg); - if (haveHits) this._handle.emit('mergedSegment', this.resp); - } - - _mergeHits(hits) { - const mergedHits = this._mergedResp.hits.hits; - const desiredSize = this._desiredSize; - const sortFn = this._sortFn; - - pushAll(hits, mergedHits); - - if (sortFn) { - mergedHits.sort(sortFn); - } - - if (_.isNumber(desiredSize)) { - this._mergedResp.hits.hits = mergedHits.slice(0, desiredSize); - } - } - - _mergeSegment(seg) { - const merged = this._mergedResp; - - this._segments.push(seg); - - merged.took += seg.took; - merged.hits.total += seg.hits.total; - merged.hits.max_score = Math.max(merged.hits.max_score, seg.hits.max_score); - - if (_.size(seg.hits.hits)) { - this._mergeHits(seg.hits.hits); - this._detectHitsWindow(merged.hits.hits); - } - - if (!seg.aggregations) return; - - Object.keys(seg.aggregations).forEach(function (aggKey) { - - if (!merged.aggregations) { - // start merging aggregations - merged.aggregations = {}; - merged._bucketIndex = {}; - } - - if (!merged.aggregations[aggKey]) { - merged.aggregations[aggKey] = { - buckets: [] - }; - } - - seg.aggregations[aggKey].buckets.forEach(function (bucket) { - let mbucket = merged._bucketIndex[bucket.key]; - if (mbucket) { - mbucket.doc_count += bucket.doc_count; - return; - } - - mbucket = merged._bucketIndex[bucket.key] = bucket; - merged.aggregations[aggKey].buckets.push(mbucket); - }); - }); - } - - _detectHitsWindow(hits) { - hits = hits || []; - const indexPattern = this.source.getField('index'); - const desiredSize = this._desiredSize; - - const size = _.size(hits); - if (!_.isNumber(desiredSize) || size < desiredSize) { - this._hitWindow = { - size: size, - min: -Infinity, - max: Infinity - }; - return; - } - - let min; - let max; - - hits.forEach(function (deepHit) { - const hit = indexPattern.flattenHit(deepHit); - const time = hit[indexPattern.timeFieldName]; - if (min == null || time < min) min = time; - if (max == null || time > max) max = time; - }); - - this._hitWindow = { size, min, max }; - } - - _pickSizeForIndices(indices) { - const hitWindow = this._hitWindow; - const desiredSize = this._desiredSize; - - if (!_.isNumber(desiredSize)) return null; - // we don't have any hits yet, get us more info! - if (!hitWindow) return desiredSize; - // the order of documents isn't important, just get us more - if (!this._sortFn) return Math.max(desiredSize - hitWindow.size, 0); - // if all of the documents in every index fall outside of our current doc set, we can ignore them. - const someOverlap = indices.some(function (index) { - return index.min <= hitWindow.max && hitWindow.min <= index.max; - }); - - return someOverlap ? desiredSize : 0; - } - } - - return SegmentedSearchRequest; -} diff --git a/src/legacy/ui/public/courier/search_source/search_source.js b/src/legacy/ui/public/courier/search_source/search_source.js index 8fc71bff40a8..7943973bf51e 100644 --- a/src/legacy/ui/public/courier/search_source/search_source.js +++ b/src/legacy/ui/public/courier/search_source/search_source.js @@ -76,7 +76,6 @@ import { buildEsQuery, getEsQueryConfig, filterMatchesIndex } from '@kbn/es-quer import '../../promises'; import { NormalizeSortRequestProvider } from './_normalize_sort_request'; import { SearchRequestProvider } from '../fetch/request'; -import { SegmentedSearchRequestProvider } from '../fetch/request/segmented_search_request'; import { searchRequestQueue } from '../search_request_queue'; import { FetchSoonProvider } from '../fetch'; @@ -117,7 +116,6 @@ function isIndexPattern(val) { export function SearchSourceProvider(Promise, Private, config) { const SearchRequest = Private(SearchRequestProvider); - const SegmentedSearchRequest = Private(SegmentedSearchRequestProvider); const normalizeSortRequest = Private(NormalizeSortRequestProvider); const fetchSoon = Private(FetchSoonProvider); const { fieldWildcardFilter } = Private(FieldWildcardProvider); @@ -390,26 +388,6 @@ export function SearchSourceProvider(Promise, Private, config) { }); } - onBeginSegmentedFetch(initFunction) { - const self = this; - return new Promise((resolve, reject) => { - function addRequest() { - const defer = Promise.defer(); - const errorHandler = (request, error) => { - reject(error); - request.abort(); - }; - const req = new SegmentedSearchRequest({ source: self, defer, errorHandler, initFn: initFunction }); - - // Return promises created by the completion handler so that - // errors will bubble properly - return req.getCompletePromise().then(addRequest); - } - - addRequest(); - }); - } - async getSearchRequestBody() { const searchRequest = await this._flatten(); return searchRequest.body; diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 2e521829aaf8..3312215623b4 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -815,8 +815,6 @@ "kbn.advancedSettings.courier.ignoreFilterTitle": "忽略筛选", "kbn.advancedSettings.courier.maxRequestsText": "控制用于 Kibana 发送的 _msearch 请求的 “{maxRequestsLink}” 设置。设置为 0 可禁用此配置并使用 Elasticsearch 默认值。", "kbn.advancedSettings.courier.maxRequestsTitle": "最大并发分片请求数", - "kbn.advancedSettings.courier.maxSegmentCountText": "Discover 中的请求将拆分成段,以防止大型请求发送给 Elasticsearch。此设置会尝试阻止段列表过长,否则会导致系统花费很长时间处理请求。", - "kbn.advancedSettings.courier.maxSegmentCountTitle": "最大段计数", "kbn.advancedSettings.courier.requestPreferenceText": "允许您设置用于处理搜索请求的分片。", "kbn.advancedSettings.courier.requestPreferenceTitle": "请求首选项", "kbn.advancedSettings.csv.quoteValuesText": "在 csv 导出中是否应使用引号引起值?", @@ -1280,8 +1278,6 @@ "kbn.discover.hitsPluralTitle": "{hits, plural, one {次命中} other {次命中}}", "kbn.discover.howToChangeTheTimeTooltip": "要更改时间,请单击导航栏中的时钟图标", "kbn.discover.howToSeeOtherMatchingDocumentsDescription": "以下是匹配您的搜索的前 {sampleSize} 个文档,请优化您的搜索以查看其他文档。", - "kbn.discover.inspectorRequest.segmentFetchCompleteStatusDescription": "此请求将查询 Elasticsearch 以获取搜索的数据。", - "kbn.discover.inspectorRequest.segmentFetchCompleteStatusTitle": "段 {fetchCompleteStatus}", "kbn.discover.localMenu.inspectTitle": "检查", "kbn.discover.localMenu.localMenu.newSearchTitle": "新建", "kbn.discover.localMenu.newSearchDescription": "新搜索", @@ -8174,4 +8170,4 @@ "xpack.watcher.watchActionsTitle": "满足后将执行 {watchActionsCount, plural, one{# 个操作} other {# 个操作}}", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +}