From 115fa6b23ea09c24ac8a0d5d360f327fe18f22ae Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 23 Dec 2019 14:02:59 +0000 Subject: [PATCH 01/46] deprecate msearch --- src/legacy/core_plugins/data/index.ts | 1 - src/legacy/core_plugins/data/public/legacy.ts | 4 +- src/legacy/core_plugins/data/public/plugin.ts | 17 +++++- .../data/public/search/expressions/boot.ts | 6 ++- .../data/public/search/expressions/esaggs.ts | 8 +-- .../public/search/fetch/call_client.test.ts | 2 +- .../data/public/search/fetch/call_client.ts | 4 +- .../data/public/search/fetch/fetch_soon.ts | 12 +++-- .../data/public/search/fetch/types.ts | 3 +- .../search/search_source/search_source.ts | 27 ++++++---- .../default_search_strategy.test.ts | 33 +----------- .../default_search_strategy.ts | 54 +++++++------------ src/plugins/data/public/services.ts | 8 +++ 13 files changed, 80 insertions(+), 99 deletions(-) diff --git a/src/legacy/core_plugins/data/index.ts b/src/legacy/core_plugins/data/index.ts index c91500cd545d4..77a856fe85180 100644 --- a/src/legacy/core_plugins/data/index.ts +++ b/src/legacy/core_plugins/data/index.ts @@ -35,7 +35,6 @@ export default function DataPlugin(kibana: any) { }, init: (server: Legacy.Server) => ({}), uiExports: { - interpreter: ['plugins/data/search/expressions/boot'], injectDefaultVars: () => ({}), styleSheetPaths: resolve(__dirname, 'public/index.scss'), mappings, diff --git a/src/legacy/core_plugins/data/public/legacy.ts b/src/legacy/core_plugins/data/public/legacy.ts index a6646ea338c93..35d584b146186 100644 --- a/src/legacy/core_plugins/data/public/legacy.ts +++ b/src/legacy/core_plugins/data/public/legacy.ts @@ -39,7 +39,9 @@ import { plugin } from '.'; const dataPlugin = plugin(); -export const setup = dataPlugin.setup(npSetup.core); +export const setup = dataPlugin.setup(npSetup.core, { + expressions: npSetup.plugins.expressions, +}); export const start = dataPlugin.start(npStart.core, { data: npStart.plugins.data, diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 893e477b38583..211cf3eb3ee29 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -20,14 +20,22 @@ import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { SearchService, SearchStart } from './search'; import { DataPublicPluginStart } from '../../../../plugins/data/public'; +import { ExpressionsSetup } from '../../../../plugins/expressions/public'; import { setFieldFormats, setNotifications, setIndexPatterns, setQueryService, + setSearchService, + setUiSettings, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; +import { loadEsaggs } from './search/expressions/boot'; + +export interface DataPluginSetupDependencies { + expressions: ExpressionsSetup; +} export interface DataPluginStartDependencies { data: DataPublicPluginStart; @@ -54,18 +62,23 @@ export interface DataStart { * or static code. */ -export class DataPlugin implements Plugin { +export class DataPlugin + implements Plugin { private readonly search = new SearchService(); - public setup(core: CoreSetup) {} + public setup(core: CoreSetup, { expressions }: DataPluginSetupDependencies) { + loadEsaggs(expressions); + } public start(core: CoreStart, { data }: DataPluginStartDependencies): DataStart { // This is required for when Angular code uses Field and FieldList. setFieldFormats(data.fieldFormats); setQueryService(data.query); + setSearchService(data.search); setIndexPatterns(data.indexPatterns); setFieldFormats(data.fieldFormats); setNotifications(core.notifications); + setUiSettings(core.uiSettings); return { search: this.search.start(core), diff --git a/src/legacy/core_plugins/data/public/search/expressions/boot.ts b/src/legacy/core_plugins/data/public/search/expressions/boot.ts index 29348383ce6fe..a6f5b764ddc7e 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/boot.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/boot.ts @@ -17,7 +17,9 @@ * under the License. */ -import { npSetup } from 'ui/new_platform'; +import { ExpressionsSetup } from 'src/plugins/expressions/public'; import { esaggs } from './esaggs'; -npSetup.plugins.expressions.registerFunction(esaggs); +export function loadEsaggs(expressions: ExpressionsSetup) { + expressions.registerFunction(esaggs); +} diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index 4ec4dbd7f88d6..bd068103bb5c2 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -34,12 +34,6 @@ import { getTime, FilterManager, } from '../../../../../../plugins/data/public'; -import { - SearchSource, - ISearchSource, - getRequestInspectorStats, - getResponseInspectorStats, -} from '../../../../../ui/public/courier'; import { buildTabularInspectorData } from '../../../../../ui/public/inspector/build_tabular_inspector_data'; import { calculateObjectHash } from '../../../../visualizations/public'; @@ -49,6 +43,8 @@ import { PersistedState } from '../../../../../ui/public/persisted_state'; import { Adapters } from '../../../../../../plugins/inspector/public'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { getQueryService, getIndexPatterns } from '../../../../../../plugins/data/public/services'; +import { ISearchSource, getRequestInspectorStats, getResponseInspectorStats } from '../..'; +import { SearchSource } from '../search_source'; export interface RequestHandlerParams { searchSource: ISearchSource; diff --git a/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts b/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts index 74c87d77dd4fd..24a36c9db9df7 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/call_client.test.ts @@ -76,7 +76,7 @@ describe('callClient', () => { test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { es: {}, config: {}, esShardTimeout: 0 } as FetchHandlers; + const args = { searchService: {}, config: {}, esShardTimeout: 0 } as FetchHandlers; callClient(searchRequests, [], args); diff --git a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts b/src/legacy/core_plugins/data/public/search/fetch/call_client.ts index 43da27f941e4e..a4dbbaf106d7e 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/call_client.ts @@ -26,7 +26,7 @@ import { SearchRequest } from '../types'; export function callClient( searchRequests: SearchRequest[], requestsOptions: FetchOptions[] = [], - { es, config, esShardTimeout }: FetchHandlers + { searchService, config, esShardTimeout }: FetchHandlers ) { // Correlate the options with the request that they're associated with const requestOptionEntries: Array<[ @@ -53,7 +53,7 @@ export function callClient( // then an error would have been thrown above const { searching, abort } = searchStrategy!.search({ searchRequests: requests, - es, + searchService, config, esShardTimeout, }); diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts index 75de85e02a1a2..ffab8d3b41a10 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts @@ -28,10 +28,10 @@ import { SearchRequest, SearchResponse } from '../types'; export async function fetchSoon( request: SearchRequest, options: FetchOptions, - { es, config, esShardTimeout }: FetchHandlers + { searchService, config, esShardTimeout }: FetchHandlers ) { const msToDelay = config.get('courier:batchSearches') ? 50 : 0; - return delayedFetch(request, options, { es, config, esShardTimeout }, msToDelay); + return delayedFetch(request, options, { searchService, config, esShardTimeout }, msToDelay); } /** @@ -64,7 +64,7 @@ let fetchInProgress: Promise | null = null; async function delayedFetch( request: SearchRequest, options: FetchOptions, - { es, config, esShardTimeout }: FetchHandlers, + { searchService, config, esShardTimeout }: FetchHandlers, ms: number ) { const i = requestsToFetch.length; @@ -73,7 +73,11 @@ async function delayedFetch( const responses = await (fetchInProgress = fetchInProgress || delay(() => { - const response = callClient(requestsToFetch, requestOptions, { es, config, esShardTimeout }); + const response = callClient(requestsToFetch, requestOptions, { + searchService, + config, + esShardTimeout, + }); requestsToFetch = []; requestOptions = []; fetchInProgress = null; diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts index 0887a1f84c7c8..fba14119d83c3 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/types.ts @@ -17,6 +17,7 @@ * under the License. */ +import { ISearchStart } from 'src/plugins/data/public'; import { IUiSettingsClient } from '../../../../../../core/public'; import { SearchRequest, SearchResponse } from '../types'; @@ -35,7 +36,7 @@ export interface FetchOptions { } export interface FetchHandlers { - es: ApiCaller; + searchService: ISearchStart; config: IUiSettingsClient; esShardTimeout: number; } diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 6efcae4d4b88d..88282944db4e2 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -71,7 +71,6 @@ import _ from 'lodash'; import { npSetup } from 'ui/new_platform'; -import chrome from 'ui/chrome'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -79,10 +78,13 @@ import { getHighlightRequest, esFilters, esQuery } from '../../../../../../plugi import { RequestFailure } from '../fetch/errors'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { SearchSourceOptions, SearchSourceFields, SearchRequest } from './types'; -import { FetchOptions, ApiCaller } from '../fetch/types'; +import { FetchOptions } from '../fetch/types'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { getSearchService, getUiSettings } from '../../../../../../plugins/data/public/services'; + +// TODO: remove const esShardTimeout = npSetup.core.injectedMetadata.getInjectedVar('esShardTimeout') as number; -const config = npSetup.core.uiSettings; export type ISearchSource = Pick; @@ -192,9 +194,8 @@ export class SearchSource { * @async */ async fetch(options: FetchOptions = {}) { - const $injector = await chrome.dangerouslyGetActiveInjector(); - const es = $injector.get('es') as ApiCaller; - + const searchService = getSearchService(); + const config = getUiSettings(); await this.requestIsStarting(options); const searchRequest = await this.flatten(); @@ -206,7 +207,7 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { es, config, esShardTimeout } + { searchService, config, esShardTimeout } ); if (response.error) { @@ -313,7 +314,11 @@ export class SearchSource { case 'source': return addToBody('_source', val); case 'sort': - const sort = normalizeSortRequest(val, this.getField('index'), config.get('sort:options')); + const sort = normalizeSortRequest( + val, + this.getField('index'), + getUiSettings().get('sort:options') + ); return addToBody(key, sort); default: return addToBody(key, val); @@ -359,7 +364,7 @@ export class SearchSource { if (body._source) { // exclude source fields for this index pattern specified by the user - const filter = fieldWildcardFilter(body._source.excludes, config.get('metaFields')); + const filter = fieldWildcardFilter(body._source.excludes, getUiSettings().get('metaFields')); body.docvalue_fields = body.docvalue_fields.filter((docvalueField: any) => filter(docvalueField.field) ); @@ -377,11 +382,11 @@ export class SearchSource { _.set(body, '_source.includes', remainingFields); } - const esQueryConfigs = esQuery.getEsQueryConfig(config); + const esQueryConfigs = esQuery.getEsQueryConfig(getUiSettings()); body.query = esQuery.buildEsQuery(index, query, filters, esQueryConfigs); if (highlightAll && body.query) { - body.highlight = getHighlightRequest(body.query, config.get('doc_table:highlight')); + body.highlight = getHighlightRequest(body.query, getUiSettings().get('doc_table:highlight')); delete searchRequest.highlightAll; } diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index 0ec6a6c2e143e..600e17c5ed332 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -55,43 +55,12 @@ describe('defaultSearchStrategy', function() { }, ], esShardTimeout: 0, - es: { - msearch: msearchMock, + searchService: { search: searchMock, }, }; }); - test('does not send max_concurrent_shard_requests by default', async () => { - const config = getConfigStub({ 'courier:batchSearches': true }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); - }); - - test('allows configuration of max_concurrent_shard_requests', async () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - 'courier:maxConcurrentShardRequests': 42, - }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); - }); - - test('should set rest_total_hits_as_int to true on a request', async () => { - const config = getConfigStub({ 'courier:batchSearches': true }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); - }); - - test('should set ignore_throttled=false when including frozen indices', async () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - 'search:includeFrozen': true, - }); - await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); - }); - test('should properly call abort with msearch', () => { const config = getConfigStub({ 'courier:batchSearches': true, diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index 9bfa1df71aa81..5f4b8ae71acf2 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -19,18 +19,13 @@ import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; import { isDefaultTypeIndexPattern } from './is_default_type_index_pattern'; -import { - getSearchParams, - getMSearchParams, - getPreference, - getTimeout, -} from '../fetch/get_search_params'; +import { getSearchParams } from '../fetch/get_search_params'; export const defaultSearchStrategy: SearchStrategyProvider = { id: 'default', search: params => { - return params.config.get('courier:batchSearches') ? msearch(params) : search(params); + return search(params); }, isViable: indexPattern => { @@ -38,38 +33,25 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { - const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { - const inlineHeader = { - index: index.title || index, - search_type: searchType, - ignore_unavailable: true, - preference: getPreference(config), - }; - const inlineBody = { - ...body, - timeout: getTimeout(esShardTimeout), - }; - return `${JSON.stringify(inlineHeader)}\n${JSON.stringify(inlineBody)}`; - }); - - const searching = es.msearch({ - ...getMSearchParams(config), - body: `${inlineRequests.join('\n')}\n`, - }); - return { - searching: searching.then(({ responses }) => responses), - abort: searching.abort, - }; -} - -function search({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { +function search({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { const abortController = new AbortController(); const searchParams = getSearchParams(config, esShardTimeout); const promises = searchRequests.map(({ index, body }) => { - const searching = es.search({ index: index.title || index, body, ...searchParams }); - abortController.signal.addEventListener('abort', searching.abort); - return searching.catch(({ response }) => JSON.parse(response)); + const params = { + index: index.title || index, + body, + ...searchParams, + }; + const { signal } = abortController; + return searchService + .search({ params }, { signal }) + .toPromise() + .then(({ rawResponse }) => rawResponse); }); return { searching: Promise.all(promises), diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index 76b3283220f67..609b510a82f7b 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -28,6 +28,10 @@ export const [getNotifications, setNotifications] = createGetterSetter( + 'UiSettings' +); + export const [getFieldFormats, setFieldFormats] = createGetterSetter( 'FieldFormats' ); @@ -41,3 +45,7 @@ export const [getIndexPatterns, setIndexPatterns] = createGetterSetter('Query'); + +export const [getSearchService, setSearchService] = createGetterSetter< + DataPublicPluginStart['search'] +>('Search'); From 87ae717dd4cc77e09179f9ae8fbb8115ec4c5f85 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 23 Dec 2019 15:54:43 +0000 Subject: [PATCH 02/46] Missing export --- .../core_plugins/visualizations/public/np_ready/public/index.ts | 2 ++ .../vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts index 2e9d055858a48..29ff812b95473 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts @@ -52,3 +52,5 @@ export { buildPipeline, buildVislibDimensions, SchemaConfig } from './legacy/bui // @ts-ignore export { updateOldState } from './legacy/vis_update_state'; export { calculateObjectHash } from './legacy/calculate_object_hash'; +// @ts-ignore +export { createFiltersFromEvent } from './filters/vis_filters'; diff --git a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx index f0100e369f050..646130353deae 100644 --- a/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx +++ b/src/legacy/ui/public/vis/vis_types/vislib_vis_legend/vislib_vis_legend.tsx @@ -25,7 +25,6 @@ import { EuiPopoverProps, EuiIcon, keyCodes, htmlIdGenerator } from '@elastic/eu // @ts-ignore import { Data } from '../../../vislib/lib/data'; -// @ts-ignore import { createFiltersFromEvent } from '../../../../../core_plugins/visualizations/public'; import { CUSTOM_LEGEND_VIS_TYPES, LegendItem } from './models'; import { VisLegendItem } from './vislib_vis_legend_item'; From 0593782da85550e918f7d61b3590793aaa077447 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 23 Dec 2019 16:23:50 +0000 Subject: [PATCH 03/46] adjust tests, revert loading method of esaggs/boot --- src/legacy/core_plugins/data/index.ts | 1 + src/legacy/core_plugins/data/public/legacy.ts | 4 +--- src/legacy/core_plugins/data/public/plugin.ts | 5 +---- .../core_plugins/data/public/search/expressions/boot.ts | 6 ++---- .../search/expressions}/build_tabular_inspector_data.ts | 4 ++-- .../core_plugins/data/public/search/expressions/esaggs.ts | 2 +- .../core_plugins/visualizations/public/legacy_imports.ts | 1 - .../public/components/visualization_requesterror.tsx | 2 +- 8 files changed, 9 insertions(+), 16 deletions(-) rename src/legacy/{ui/public/inspector => core_plugins/data/public/search/expressions}/build_tabular_inspector_data.ts (95%) diff --git a/src/legacy/core_plugins/data/index.ts b/src/legacy/core_plugins/data/index.ts index 77a856fe85180..c91500cd545d4 100644 --- a/src/legacy/core_plugins/data/index.ts +++ b/src/legacy/core_plugins/data/index.ts @@ -35,6 +35,7 @@ export default function DataPlugin(kibana: any) { }, init: (server: Legacy.Server) => ({}), uiExports: { + interpreter: ['plugins/data/search/expressions/boot'], injectDefaultVars: () => ({}), styleSheetPaths: resolve(__dirname, 'public/index.scss'), mappings, diff --git a/src/legacy/core_plugins/data/public/legacy.ts b/src/legacy/core_plugins/data/public/legacy.ts index 35d584b146186..a6646ea338c93 100644 --- a/src/legacy/core_plugins/data/public/legacy.ts +++ b/src/legacy/core_plugins/data/public/legacy.ts @@ -39,9 +39,7 @@ import { plugin } from '.'; const dataPlugin = plugin(); -export const setup = dataPlugin.setup(npSetup.core, { - expressions: npSetup.plugins.expressions, -}); +export const setup = dataPlugin.setup(npSetup.core); export const start = dataPlugin.start(npStart.core, { data: npStart.plugins.data, diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 211cf3eb3ee29..f10cb19cc3927 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -31,7 +31,6 @@ import { setUiSettings, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; -import { loadEsaggs } from './search/expressions/boot'; export interface DataPluginSetupDependencies { expressions: ExpressionsSetup; @@ -66,9 +65,7 @@ export class DataPlugin implements Plugin { private readonly search = new SearchService(); - public setup(core: CoreSetup, { expressions }: DataPluginSetupDependencies) { - loadEsaggs(expressions); - } + public setup(core: CoreSetup) {} public start(core: CoreStart, { data }: DataPluginStartDependencies): DataStart { // This is required for when Angular code uses Field and FieldList. diff --git a/src/legacy/core_plugins/data/public/search/expressions/boot.ts b/src/legacy/core_plugins/data/public/search/expressions/boot.ts index a6f5b764ddc7e..29348383ce6fe 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/boot.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/boot.ts @@ -17,9 +17,7 @@ * under the License. */ -import { ExpressionsSetup } from 'src/plugins/expressions/public'; +import { npSetup } from 'ui/new_platform'; import { esaggs } from './esaggs'; -export function loadEsaggs(expressions: ExpressionsSetup) { - expressions.registerFunction(esaggs); -} +npSetup.plugins.expressions.registerFunction(esaggs); diff --git a/src/legacy/ui/public/inspector/build_tabular_inspector_data.ts b/src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts similarity index 95% rename from src/legacy/ui/public/inspector/build_tabular_inspector_data.ts rename to src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts index b09ed60e7186f..6e6d2a15fa2ac 100644 --- a/src/legacy/ui/public/inspector/build_tabular_inspector_data.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/build_tabular_inspector_data.ts @@ -19,8 +19,8 @@ import { set } from 'lodash'; // @ts-ignore -import { createFilter } from '../../../core_plugins/visualizations/public'; -import { FormattedData } from './adapters'; +import { createFilter } from '../../../../visualizations/public'; +import { FormattedData } from '../../../../../../plugins/inspector/public'; interface Column { id: string; diff --git a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts index bd068103bb5c2..889c747c9a62e 100644 --- a/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts +++ b/src/legacy/core_plugins/data/public/search/expressions/esaggs.ts @@ -35,7 +35,7 @@ import { FilterManager, } from '../../../../../../plugins/data/public'; -import { buildTabularInspectorData } from '../../../../../ui/public/inspector/build_tabular_inspector_data'; +import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { calculateObjectHash } from '../../../../visualizations/public'; // @ts-ignore import { tabifyAggResponse } from '../../../../../ui/public/agg_response/tabify/tabify'; diff --git a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts index 92d8ac2c7db3a..ce29a482bcd01 100644 --- a/src/legacy/core_plugins/visualizations/public/legacy_imports.ts +++ b/src/legacy/core_plugins/visualizations/public/legacy_imports.ts @@ -18,7 +18,6 @@ */ export { PersistedState } from '../../../ui/public/persisted_state'; -export { SearchError } from '../../../ui/public/courier/search_strategy/search_error'; export { AggConfig } from '../../../ui/public/agg_types/agg_config'; export { AggConfigs } from '../../../ui/public/agg_types/agg_configs'; export { diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx index 8b9fded919f13..1af9aa3c3e602 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/components/visualization_requesterror.tsx @@ -19,7 +19,7 @@ import { EuiIcon, EuiSpacer, EuiText } from '@elastic/eui'; import React from 'react'; -import { SearchError } from '../../../legacy_imports'; +import { SearchError } from '../../../../../data/public/search/search_strategy'; interface VisualizationRequestErrorProps { onInit?: () => void; From 81ef64dbed8034fd784782ea859cc58ae5716567 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 23 Dec 2019 16:32:26 +0000 Subject: [PATCH 04/46] getInjectedMetadata --- src/legacy/core_plugins/data/public/plugin.ts | 5 ++++- .../public/search/search_source/search_source.ts | 13 +++++++------ src/plugins/data/public/services.ts | 6 +++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index f10cb19cc3927..d8d3975238712 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -29,6 +29,7 @@ import { setQueryService, setSearchService, setUiSettings, + setInjectedMetadata, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; @@ -65,7 +66,9 @@ export class DataPlugin implements Plugin { private readonly search = new SearchService(); - public setup(core: CoreSetup) {} + public setup(core: CoreSetup) { + setInjectedMetadata(core.injectedMetadata); + } public start(core: CoreStart, { data }: DataPluginStartDependencies): DataStart { // This is required for when Angular code uses Field and FieldList. diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 88282944db4e2..7beeb087242f6 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -70,7 +70,6 @@ */ import _ from 'lodash'; -import { npSetup } from 'ui/new_platform'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -80,11 +79,12 @@ import { filterDocvalueFields } from './filter_docvalue_fields'; import { SearchSourceOptions, SearchSourceFields, SearchRequest } from './types'; import { FetchOptions } from '../fetch/types'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { getSearchService, getUiSettings } from '../../../../../../plugins/data/public/services'; - -// TODO: remove -const esShardTimeout = npSetup.core.injectedMetadata.getInjectedVar('esShardTimeout') as number; +import { + getSearchService, + getUiSettings, + getInjectedMetadata, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../../plugins/data/public/services'; export type ISearchSource = Pick; @@ -200,6 +200,7 @@ export class SearchSource { const searchRequest = await this.flatten(); this.history = [searchRequest]; + const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number; const response = await fetchSoon( searchRequest, diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index 609b510a82f7b..7ebcd9eed3981 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -18,7 +18,7 @@ */ import { NotificationsStart } from 'src/core/public'; -import { CoreStart } from 'kibana/public'; +import { CoreSetup, CoreStart } from 'kibana/public'; import { FieldFormatsStart } from '.'; import { createGetterSetter } from '../../kibana_utils/public'; import { IndexPatternsContract } from './index_patterns'; @@ -46,6 +46,10 @@ export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] >('Query'); +export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< + CoreSetup['injectedMetadata'] +>('InjectedMetadata'); + export const [getSearchService, setSearchService] = createGetterSetter< DataPublicPluginStart['search'] >('Search'); From 0063499d9d3c487b0f45c450f2e21b0ea6d02dfe Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 24 Dec 2019 16:53:18 +0000 Subject: [PATCH 05/46] Fix jest tests --- .../search_source/search_source.test.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts index 28f8dba9a75de..62475c011ff90 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts @@ -19,19 +19,28 @@ import { SearchSource } from '../search_source'; import { IndexPattern } from '../../../../../../plugins/data/public'; - -jest.mock('ui/new_platform'); +import { + setSearchService, + setUiSettings, + setInjectedMetadata, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../../plugins/data/public/services'; + +import { + injectedMetadataServiceMock, + uiSettingsServiceMock, +} from '../../../../../../core/public/mocks'; + +setUiSettings(uiSettingsServiceMock.createStartContract()); +setInjectedMetadata(injectedMetadataServiceMock.createSetupContract()); +setSearchService({ + search: jest.fn(), +}); jest.mock('../fetch', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), })); -jest.mock('ui/chrome', () => ({ - dangerouslyGetActiveInjector: () => ({ - get: jest.fn(), - }), -})); - const getComputedFields = () => ({ storedFields: [], scriptFields: [], From 8e999d18789916edc3046545f46a412655e8f08f Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 24 Dec 2019 17:24:38 +0000 Subject: [PATCH 06/46] update default strategy abort test --- .../default_search_strategy.test.ts | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index 600e17c5ed332..2e9cbbfddf7b7 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -29,22 +29,17 @@ function getConfigStub(config: any = {}) { } as IUiSettingsClient; } -const msearchMockResponse: any = Promise.resolve([]); -msearchMockResponse.abort = jest.fn(); -const msearchMock = jest.fn().mockReturnValue(msearchMockResponse); - const searchMockResponse: any = Promise.resolve([]); searchMockResponse.abort = jest.fn(); -const searchMock = jest.fn().mockReturnValue(searchMockResponse); +const searchMock = jest.fn().mockReturnValue({ + toPromise: () => searchMockResponse, +}); describe('defaultSearchStrategy', function() { describe('search', function() { let searchArgs: MockedKeys>; beforeEach(() => { - msearchMockResponse.abort.mockClear(); - msearchMock.mockClear(); - searchMockResponse.abort.mockClear(); searchMock.mockClear(); @@ -61,20 +56,17 @@ describe('defaultSearchStrategy', function() { }; }); - test('should properly call abort with msearch', () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - }); - search({ ...searchArgs, config }).abort(); - expect(msearchMockResponse.abort).toHaveBeenCalled(); + test('should call search service', () => { + const config = getConfigStub(); + search({ ...searchArgs, config }); + expect(searchMock).toHaveBeenCalled(); }); test('should properly abort with search', async () => { - const config = getConfigStub({ - 'courier:batchSearches': false, - }); + const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); + const config = getConfigStub({}); search({ ...searchArgs, config }).abort(); - expect(searchMockResponse.abort).toHaveBeenCalled(); + expect(abortSpy).toHaveBeenCalled(); }); }); }); From dfcb01b85e1e939b4e8b8bee0c907ed09ee56cb3 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 2 Jan 2020 12:03:51 +0200 Subject: [PATCH 07/46] notice update --- NOTICE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.txt b/NOTICE.txt index 230e511746022..955c3127fa955 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -1,5 +1,5 @@ Kibana source code with Kibana X-Pack source code -Copyright 2012-2019 Elasticsearch B.V. +Copyright 2012-2020 Elasticsearch B.V. --- Pretty handling of logarithmic axes. From 2d8c3a3a3167abc83eb23e6fb03e7e463a34e68a Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 2 Jan 2020 13:43:35 +0200 Subject: [PATCH 08/46] Allow running discover errors test independently --- test/functional/apps/discover/_errors.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/discover/_errors.js b/test/functional/apps/discover/_errors.js index 53dcd8cc9e5c1..7dbb93c884f46 100644 --- a/test/functional/apps/discover/_errors.js +++ b/test/functional/apps/discover/_errors.js @@ -22,10 +22,11 @@ import expect from '@kbn/expect'; export default function({ getService, getPageObjects }) { const esArchiver = getService('esArchiver'); const testSubjects = getService('testSubjects'); - const PageObjects = getPageObjects(['common']); + const PageObjects = getPageObjects(['common', 'discover']); describe('errors', function describeIndexTests() { before(async function() { + await esArchiver.loadIfNeeded('logstash_functional'); await esArchiver.load('invalid_scripted_field'); await PageObjects.common.navigateToApp('discover'); }); From c665b75495851bd72ef754ea0b4e7c9aff669e95 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 2 Jan 2020 14:30:59 +0200 Subject: [PATCH 09/46] Remove batchSearches --- src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts index ffab8d3b41a10..fdfc73e3b12e4 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts @@ -30,8 +30,7 @@ export async function fetchSoon( options: FetchOptions, { searchService, config, esShardTimeout }: FetchHandlers ) { - const msToDelay = config.get('courier:batchSearches') ? 50 : 0; - return delayedFetch(request, options, { searchService, config, esShardTimeout }, msToDelay); + return delayedFetch(request, options, { searchService, config, esShardTimeout }, 0); } /** From 726e9e3b3c961acd67356efce7936b5b6c9311c9 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 2 Jan 2020 15:13:57 +0200 Subject: [PATCH 10/46] Detect painless script error --- .../np_ready/angular/get_painless_error.ts | 18 ++++++++---------- src/plugins/data/server/search/routes.ts | 2 +- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index 212fd870a5aeb..018cce73130b6 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -18,24 +18,22 @@ */ import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; export function getPainlessError(error: Error) { - const rootCause: Array<{ lang: string; script: string }> | undefined = get( - error, - 'resp.error.root_cause' - ); - - if (!rootCause) { + const errorBody = (error as any).body; + if (!errorBody || errorBody.statusCode !== 400) { return; } - const [{ lang, script }] = rootCause; - - if (lang !== 'painless') { + // The response from the new endpoint does not contain a rootCause. + // What would be the proper way to handle this? + if (!errorBody.message.startsWith('[script_exception]')) { return; } + const lang = 'painless'; + const script = ''; + return { lang, script, diff --git a/src/plugins/data/server/search/routes.ts b/src/plugins/data/server/search/routes.ts index eaa72548e08ee..028324766b0e8 100644 --- a/src/plugins/data/server/search/routes.ts +++ b/src/plugins/data/server/search/routes.ts @@ -39,7 +39,7 @@ export function registerSearchRoute(router: IRouter): void { const response = await context.search!.search(searchRequest, {}, strategy); return res.ok({ body: response }); } catch (err) { - return res.internalError({ body: err }); + return res.customError({ statusCode: err.statusCode, body: err }); } } ); From 4eb0b8dd85d99cf881eea4f395bdc692cb76da5c Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 2 Jan 2020 19:06:05 +0200 Subject: [PATCH 11/46] don't show notifications for aborted requests --- .../kibana/public/discover/np_ready/angular/discover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index abf025524522b..8a8d9e33c1b6b 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -806,7 +806,7 @@ function discoverController( .then(onResults) .catch(error => { // If the request was aborted then no need to surface this error in the UI - if (error instanceof Error && error.name === 'AbortError') return; + if (error instanceof Error && error.message === 'The user aborted a request.') return; const fetchError = getPainlessError(error); From f2510bbfee0a9a7330292ad921b7b978e727b3d8 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 5 Jan 2020 11:37:25 +0200 Subject: [PATCH 12/46] Fix jest tests --- .../data/public/search/fetch/fetch_soon.test.ts | 16 ---------------- src/plugins/data/server/search/routes.test.ts | 6 +++--- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts index 69a343c78b1e1..960ef90559fa5 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts @@ -72,22 +72,6 @@ describe('fetchSoon', () => { expect(callClient).toBeCalled(); }); - test('should delay by 50ms if config is set to batch searches', () => { - const config = getConfigStub({ - 'courier:batchSearches': true, - }); - const request = {}; - const options = {}; - - fetchSoon(request, options, { config } as FetchHandlers); - - expect(callClient).not.toBeCalled(); - jest.advanceTimersByTime(0); - expect(callClient).not.toBeCalled(); - jest.advanceTimersByTime(50); - expect(callClient).toBeCalled(); - }); - test('should send a batch of requests to callClient', () => { const config = getConfigStub({ 'courier:batchSearches': true, diff --git a/src/plugins/data/server/search/routes.test.ts b/src/plugins/data/server/search/routes.test.ts index a2394d88f3931..b2892dc13adfe 100644 --- a/src/plugins/data/server/search/routes.test.ts +++ b/src/plugins/data/server/search/routes.test.ts @@ -65,7 +65,7 @@ describe('Search service', () => { expect(mockResponse.ok.mock.calls[0][0]).toEqual({ body: 'yay' }); }); - it('handler throws internal error if the search throws an error', async () => { + it('handler throws an error if the search throws an error', async () => { const mockSearch = jest.fn().mockRejectedValue('oh no'); const mockContext = { core: { @@ -93,7 +93,7 @@ describe('Search service', () => { expect(mockSearch).toBeCalled(); expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody); expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy); - expect(mockResponse.internalError).toBeCalled(); - expect(mockResponse.internalError.mock.calls[0][0]).toEqual({ body: 'oh no' }); + expect(mockResponse.customError).toBeCalled(); + expect(mockResponse.customError.mock.calls[0][0]).toEqual({ body: 'oh no' }); }); }); From d68de49145764dc5eda329cc954133b834b89ae1 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 5 Jan 2020 14:54:44 +0200 Subject: [PATCH 13/46] Restore loader indicator --- .../public/search/create_app_mount_context_search.ts | 12 +++++++++--- src/plugins/data/public/search/search_service.ts | 8 +++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/plugins/data/public/search/create_app_mount_context_search.ts b/src/plugins/data/public/search/create_app_mount_context_search.ts index 5659a9c863dc1..45bcf4fea446c 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.ts @@ -18,7 +18,7 @@ */ import { mergeMap } from 'rxjs/operators'; -import { from } from 'rxjs'; +import { from, BehaviorSubject } from 'rxjs'; import { ISearchAppMountContext } from './i_search_app_mount_context'; import { ISearchGeneric } from './i_search'; import { @@ -30,7 +30,8 @@ import { TStrategyTypes } from './strategy_types'; import { DEFAULT_SEARCH_STRATEGY } from '../../common/search'; export const createAppMountSearchContext = ( - searchStrategies: TSearchStrategiesMap + searchStrategies: TSearchStrategiesMap, + loadingCount$: BehaviorSubject ): ISearchAppMountContext => { const getSearchStrategy = ( strategyName?: K @@ -48,7 +49,12 @@ export const createAppMountSearchContext = ( const strategyPromise = getSearchStrategy(strategyName); return from(strategyPromise).pipe( mergeMap(strategy => { - return strategy.search(request, options); + loadingCount$.next(loadingCount$.getValue() + 1); + const search$ = strategy.search(request, options); + search$.subscribe(() => { + loadingCount$.next(loadingCount$.getValue() - 1); + }); + return search$; }) ); }; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6030884c9f6b1..4144b146d1a4a 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { Plugin, CoreSetup, @@ -74,11 +75,16 @@ export class SearchService implements Plugin { private contextContainer?: IContextContainer>; private search?: ISearchGeneric; + private readonly loadingCount$ = new BehaviorSubject(0); constructor(private initializerContext: PluginInitializerContext) {} public setup(core: CoreSetup): ISearchSetup { - const search = (this.search = createAppMountSearchContext(this.searchStrategies).search); + core.http.addLoadingCountSource(this.loadingCount$); + const search = (this.search = createAppMountSearchContext( + this.searchStrategies, + this.loadingCount$ + ).search); core.application.registerMountContext<'search'>('search', () => { return { search }; }); From 74fc2772d17f4c22505ec04fd9725d52f9ced481 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 5 Jan 2020 15:29:32 +0200 Subject: [PATCH 14/46] Decreace loading count on error --- .../public/search/create_app_mount_context_search.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/data/public/search/create_app_mount_context_search.ts b/src/plugins/data/public/search/create_app_mount_context_search.ts index 45bcf4fea446c..ea95b63778074 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.ts @@ -51,8 +51,13 @@ export const createAppMountSearchContext = ( mergeMap(strategy => { loadingCount$.next(loadingCount$.getValue() + 1); const search$ = strategy.search(request, options); - search$.subscribe(() => { - loadingCount$.next(loadingCount$.getValue() - 1); + search$.subscribe({ + error: () => { + loadingCount$.next(loadingCount$.getValue() - 1); + }, + complete: () => { + loadingCount$.next(loadingCount$.getValue() - 1); + }, }); return search$; }) From 27e95dfa8e782054b1f0dea792c12de6a148ca16 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 5 Jan 2020 15:32:27 +0200 Subject: [PATCH 15/46] update search test --- .../create_app_mount_context_search.test.ts | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/plugins/data/public/search/create_app_mount_context_search.test.ts b/src/plugins/data/public/search/create_app_mount_context_search.test.ts index fa7cdbcda3082..15b85ee270bed 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.test.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.test.ts @@ -18,32 +18,35 @@ */ import { createAppMountSearchContext } from './create_app_mount_context_search'; -import { from } from 'rxjs'; +import { from, BehaviorSubject } from 'rxjs'; describe('Create app mount search context', () => { it('Returns search fn when there are no strategies', () => { - const context = createAppMountSearchContext({}); + const context = createAppMountSearchContext({}, new BehaviorSubject(0)); expect(context.search).toBeDefined(); }); it(`Search throws an error when the strategy doesn't exist`, () => { - const context = createAppMountSearchContext({}); + const context = createAppMountSearchContext({}, new BehaviorSubject(0)); expect(() => context.search({}, {}, 'noexist').toPromise()).toThrowErrorMatchingInlineSnapshot( `"Strategy with name noexist does not exist"` ); }); it(`Search fn is called on appropriate strategy name`, done => { - const context = createAppMountSearchContext({ - mysearch: search => - Promise.resolve({ - search: () => from(Promise.resolve({ percentComplete: 98 })), - }), - anothersearch: search => - Promise.resolve({ - search: () => from(Promise.resolve({ percentComplete: 0 })), - }), - }); + const context = createAppMountSearchContext( + { + mysearch: search => + Promise.resolve({ + search: () => from(Promise.resolve({ percentComplete: 98 })), + }), + anothersearch: search => + Promise.resolve({ + search: () => from(Promise.resolve({ percentComplete: 0 })), + }), + }, + new BehaviorSubject(0) + ); context.search({}, {}, 'mysearch').subscribe(response => { expect(response).toEqual({ percentComplete: 98 }); @@ -52,16 +55,19 @@ describe('Create app mount search context', () => { }); it(`Search fn is called with the passed in request object`, done => { - const context = createAppMountSearchContext({ - mysearch: search => { - return Promise.resolve({ - search: request => { - expect(request).toEqual({ greeting: 'hi' }); - return from(Promise.resolve({})); - }, - }); + const context = createAppMountSearchContext( + { + mysearch: search => { + return Promise.resolve({ + search: request => { + expect(request).toEqual({ greeting: 'hi' }); + return from(Promise.resolve({})); + }, + }); + }, }, - }); + new BehaviorSubject(0) + ); context.search({ greeting: 'hi' } as any, {}, 'mysearch').subscribe( response => {}, () => {}, From ea0213f6ebb36f39acd3ca800810f067edf31ac1 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 5 Jan 2020 18:15:19 +0200 Subject: [PATCH 16/46] Trigger digest after fetching fresh index patterns --- .../legacy/plugins/maps/public/angular/map_controller.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 75971d5dfe2a8..f60ddd5e769cb 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -364,10 +364,12 @@ app.controller( await Promise.all(getIndexPatternPromises); // ignore outdated results - if (prevIndexPatternIds !== nextIndexPatternIds) { + if (!_.isEqual(prevIndexPatternIds, nextIndexPatternIds)) { return; } - $scope.indexPatterns = indexPatterns; + $scope.$evalAsync(() => { + $scope.indexPatterns = indexPatterns; + }); } $scope.isFullScreen = false; @@ -382,7 +384,7 @@ app.controller( } const nextIndexPatternIds = getQueryableUniqueIndexPatternIds(store.getState()); - if (nextIndexPatternIds !== prevIndexPatternIds) { + if (!_.isEqual(nextIndexPatternIds, prevIndexPatternIds)) { prevIndexPatternIds = nextIndexPatternIds; updateIndexPatterns(nextIndexPatternIds); } From 056ef7dfaf8991531e900c7bd28e09fd1c54983e Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 6 Jan 2020 15:56:58 +0200 Subject: [PATCH 17/46] Revert isEqual --- x-pack/legacy/plugins/maps/public/angular/map_controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index f60ddd5e769cb..81e18a9952268 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -364,7 +364,7 @@ app.controller( await Promise.all(getIndexPatternPromises); // ignore outdated results - if (!_.isEqual(prevIndexPatternIds, nextIndexPatternIds)) { + if (prevIndexPatternIds !== nextIndexPatternIds) { return; } $scope.$evalAsync(() => { @@ -384,7 +384,7 @@ app.controller( } const nextIndexPatternIds = getQueryableUniqueIndexPatternIds(store.getState()); - if (!_.isEqual(nextIndexPatternIds, prevIndexPatternIds)) { + if (prevIndexPatternIds !== nextIndexPatternIds) { prevIndexPatternIds = nextIndexPatternIds; updateIndexPatterns(nextIndexPatternIds); } From d568a0b2c1453bd21da612dfed89642ce6b87eeb Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 6 Jan 2020 16:00:04 +0200 Subject: [PATCH 18/46] accurate revert --- x-pack/legacy/plugins/maps/public/angular/map_controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js index 81e18a9952268..eec97dc5c71e9 100644 --- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js +++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js @@ -384,7 +384,7 @@ app.controller( } const nextIndexPatternIds = getQueryableUniqueIndexPatternIds(store.getState()); - if (prevIndexPatternIds !== nextIndexPatternIds) { + if (nextIndexPatternIds !== prevIndexPatternIds) { prevIndexPatternIds = nextIndexPatternIds; updateIndexPatterns(nextIndexPatternIds); } From cf5126230b39c80dc6c428de19fcefe979a56dbc Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 7 Jan 2020 13:47:22 +0200 Subject: [PATCH 19/46] Return full error details to client from search endpoint --- .../np_ready/angular/get_painless_error.ts | 19 +++++++++---------- src/plugins/data/server/search/routes.ts | 10 +++++++++- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index 018cce73130b6..c37f586be447f 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -18,21 +18,20 @@ */ import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; export function getPainlessError(error: Error) { - const errorBody = (error as any).body; - if (!errorBody || errorBody.statusCode !== 400) { - return; - } + const rootCause: Array<{ lang: string; script: string }> | undefined = get( + error, + 'body.attributes.error.root_cause' + ); + const message: string = get(error, 'body.message'); - // The response from the new endpoint does not contain a rootCause. - // What would be the proper way to handle this? - if (!errorBody.message.startsWith('[script_exception]')) { + if (!rootCause) { return; } - const lang = 'painless'; - const script = ''; + const [{ lang, script }] = rootCause; return { lang, @@ -41,6 +40,6 @@ export function getPainlessError(error: Error) { defaultMessage: "Error with Painless scripted field '{script}'.", values: { script }, }), - error: error.message, + error: message, }; } diff --git a/src/plugins/data/server/search/routes.ts b/src/plugins/data/server/search/routes.ts index 028324766b0e8..6f726771c41b2 100644 --- a/src/plugins/data/server/search/routes.ts +++ b/src/plugins/data/server/search/routes.ts @@ -39,7 +39,15 @@ export function registerSearchRoute(router: IRouter): void { const response = await context.search!.search(searchRequest, {}, strategy); return res.ok({ body: response }); } catch (err) { - return res.customError({ statusCode: err.statusCode, body: err }); + return res.customError({ + statusCode: err.statusCode, + body: { + message: err.message, + attributes: { + error: err.body.error, + }, + }, + }); } } ); From 563b27e964eca5c488d9e0f14a45e19e81a00d6d Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 7 Jan 2020 14:09:13 +0200 Subject: [PATCH 20/46] Re-throw AbortError from http when user aborts request. --- src/core/public/http/fetch.ts | 6 +++++- .../kibana/public/discover/np_ready/angular/discover.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/public/http/fetch.ts b/src/core/public/http/fetch.ts index b86f1f5c08029..b7ceaed6e56a7 100644 --- a/src/core/public/http/fetch.ts +++ b/src/core/public/http/fetch.ts @@ -133,7 +133,11 @@ export class Fetch { try { response = await window.fetch(request); } catch (err) { - throw new HttpFetchError(err.message, request); + if (err.name === 'AbortError') { + throw err; + } else { + throw new HttpFetchError(err.message, request); + } } const contentType = response.headers.get('Content-Type') || ''; diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js index 8a8d9e33c1b6b..abf025524522b 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/discover.js @@ -806,7 +806,7 @@ function discoverController( .then(onResults) .catch(error => { // If the request was aborted then no need to surface this error in the UI - if (error instanceof Error && error.message === 'The user aborted a request.') return; + if (error instanceof Error && error.name === 'AbortError') return; const fetchError = getPainlessError(error); From 9a9ddcb4797065396c12226d9ad37bc35234ac27 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 7 Jan 2020 14:11:03 +0200 Subject: [PATCH 21/46] fix typo --- .../public/discover/np_ready/angular/get_painless_error.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index c37f586be447f..4cc6f100a55d3 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -33,6 +33,10 @@ export function getPainlessError(error: Error) { const [{ lang, script }] = rootCause; + if (lang !== 'painless') { + return; + } + return { lang, script, From 99f0382bc86248cf8bab197429f71f4ee15d71f5 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 7 Jan 2020 14:11:27 +0200 Subject: [PATCH 22/46] typo --- .../public/discover/np_ready/angular/get_painless_error.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index 4cc6f100a55d3..100d9cdac133b 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -33,9 +33,9 @@ export function getPainlessError(error: Error) { const [{ lang, script }] = rootCause; - if (lang !== 'painless') { - return; - } + if (lang !== 'painless') { + return; + } return { lang, From 5ad68ea3f314aaec889c85805e4e77e9d0236fc6 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 7 Jan 2020 17:23:26 +0200 Subject: [PATCH 23/46] Adjust routes jest test --- src/plugins/data/server/search/routes.test.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/data/server/search/routes.test.ts b/src/plugins/data/server/search/routes.test.ts index b2892dc13adfe..6ea0799f790fc 100644 --- a/src/plugins/data/server/search/routes.test.ts +++ b/src/plugins/data/server/search/routes.test.ts @@ -66,7 +66,12 @@ describe('Search service', () => { }); it('handler throws an error if the search throws an error', async () => { - const mockSearch = jest.fn().mockRejectedValue('oh no'); + const mockSearch = jest.fn().mockRejectedValue({ + message: 'oh no', + body: { + error: 'oops', + }, + }); const mockContext = { core: { elasticsearch: { @@ -94,6 +99,8 @@ describe('Search service', () => { expect(mockSearch.mock.calls[0][0]).toStrictEqual(mockBody); expect(mockSearch.mock.calls[0][2]).toBe(mockParams.strategy); expect(mockResponse.customError).toBeCalled(); - expect(mockResponse.customError.mock.calls[0][0]).toEqual({ body: 'oh no' }); + const error: any = mockResponse.customError.mock.calls[0][0]; + expect(error.body.message).toBe('oh no'); + expect(error.body.attributes.error).toBe('oops'); }); }); From d93f3073b9ed073c8cdd35acc226bab613b0f862 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 8 Jan 2020 17:15:25 +0200 Subject: [PATCH 24/46] Restore msearch using a separate es connection --- src/legacy/core_plugins/data/public/plugin.ts | 2 + .../data/public/search/fetch/call_client.ts | 6 +- .../data/public/search/fetch/fetch_soon.ts | 13 ++-- .../data/public/search/fetch/types.ts | 5 ++ .../search/search_source/search_source.ts | 40 ++++++++++-- .../default_search_strategy.test.ts | 62 +++++++++++++++++-- .../default_search_strategy.ts | 40 +++++++++++- src/plugins/data/public/plugin.ts | 9 ++- src/plugins/data/public/services.ts | 2 + 9 files changed, 156 insertions(+), 23 deletions(-) diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index d8d3975238712..5329702348207 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -30,6 +30,7 @@ import { setSearchService, setUiSettings, setInjectedMetadata, + setHttp, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; @@ -79,6 +80,7 @@ export class DataPlugin setFieldFormats(data.fieldFormats); setNotifications(core.notifications); setUiSettings(core.uiSettings); + setHttp(core.http); return { search: this.search.start(core), diff --git a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts b/src/legacy/core_plugins/data/public/search/fetch/call_client.ts index a4dbbaf106d7e..ad18775d5f144 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/call_client.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/call_client.ts @@ -26,7 +26,7 @@ import { SearchRequest } from '../types'; export function callClient( searchRequests: SearchRequest[], requestsOptions: FetchOptions[] = [], - { searchService, config, esShardTimeout }: FetchHandlers + fetchHandlers: FetchHandlers ) { // Correlate the options with the request that they're associated with const requestOptionEntries: Array<[ @@ -53,9 +53,7 @@ export function callClient( // then an error would have been thrown above const { searching, abort } = searchStrategy!.search({ searchRequests: requests, - searchService, - config, - esShardTimeout, + ...fetchHandlers, }); requests.forEach((request, i) => { diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts index fdfc73e3b12e4..4830464047ad6 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.ts @@ -28,9 +28,10 @@ import { SearchRequest, SearchResponse } from '../types'; export async function fetchSoon( request: SearchRequest, options: FetchOptions, - { searchService, config, esShardTimeout }: FetchHandlers + fetchHandlers: FetchHandlers ) { - return delayedFetch(request, options, { searchService, config, esShardTimeout }, 0); + const msToDelay = fetchHandlers.config.get('courier:batchSearches') ? 50 : 0; + return delayedFetch(request, options, fetchHandlers, msToDelay); } /** @@ -63,7 +64,7 @@ let fetchInProgress: Promise | null = null; async function delayedFetch( request: SearchRequest, options: FetchOptions, - { searchService, config, esShardTimeout }: FetchHandlers, + fetchHandlers: FetchHandlers, ms: number ) { const i = requestsToFetch.length; @@ -72,11 +73,7 @@ async function delayedFetch( const responses = await (fetchInProgress = fetchInProgress || delay(() => { - const response = callClient(requestsToFetch, requestOptions, { - searchService, - config, - esShardTimeout, - }); + const response = callClient(requestsToFetch, requestOptions, fetchHandlers); requestsToFetch = []; requestOptions = []; fetchInProgress = null; diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts index fba14119d83c3..cb845ff7d2b84 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/types.ts @@ -36,6 +36,11 @@ export interface FetchOptions { } export interface FetchHandlers { + /* + * Old ApiCaller for msearch + * @deprecated + */ + es: ApiCaller; searchService: ISearchStart; config: IUiSettingsClient; esShardTimeout: number; diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 7beeb087242f6..597dc9e63bad8 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -69,7 +69,10 @@ * `appSearchSource`. */ +// @ts-ignore +import { default as es } from 'elasticsearch-browser/elasticsearch'; import _ from 'lodash'; +import { CoreStart } from 'kibana/public'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -77,12 +80,13 @@ import { getHighlightRequest, esFilters, esQuery } from '../../../../../../plugi import { RequestFailure } from '../fetch/errors'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { SearchSourceOptions, SearchSourceFields, SearchRequest } from './types'; -import { FetchOptions } from '../fetch/types'; +import { FetchOptions, ApiCaller } from '../fetch/types'; import { getSearchService, getUiSettings, getInjectedMetadata, + getHttp, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; @@ -97,8 +101,21 @@ export class SearchSource { > = []; private inheritOptions: SearchSourceOptions = {}; public history: SearchRequest[] = []; - - constructor(private fields: SearchSourceFields = {}) {} + esCli: ApiCaller; + + constructor(private fields: SearchSourceFields = {}) { + const http = getHttp(); + const esRequestTimeout = getInjectedMetadata().getInjectedVar('esRequestTimeout') as number; + const esApiVersion = getInjectedMetadata().getInjectedVar('esApiVersion') as string; + + // Use legacy es client for msearch. + this.esCli = es.Client({ + host: this.getEsUrl(http), + log: 'info', + requestTimeout: esRequestTimeout, + apiVersion: esApiVersion, + }); + } /** *** * PUBLIC API @@ -188,6 +205,19 @@ export class SearchSource { return this.parent; } + getEsUrl(http: CoreStart['http']) { + const a = document.createElement('a'); + a.href = http.basePath.prepend('/elasticsearch'); + const protocolPort = /https/.test(a.protocol) ? 443 : 80; + const port = a.port || protocolPort; + return { + host: a.hostname, + port, + protocol: a.protocol, + pathname: a.pathname, + }; + } + /** * Fetch this source and reject the returned Promise on error * @@ -196,10 +226,12 @@ export class SearchSource { async fetch(options: FetchOptions = {}) { const searchService = getSearchService(); const config = getUiSettings(); + await this.requestIsStarting(options); const searchRequest = await this.flatten(); this.history = [searchRequest]; + const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number; const response = await fetchSoon( @@ -208,7 +240,7 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout } + { searchService, config, esShardTimeout, es: this.esCli } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index 2e9cbbfddf7b7..8d70943a404a4 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -29,9 +29,17 @@ function getConfigStub(config: any = {}) { } as IUiSettingsClient; } +const msearchMockResponse: any = Promise.resolve([]); +msearchMockResponse.abort = jest.fn(); +const msearchMock = jest.fn().mockReturnValue(msearchMockResponse); + const searchMockResponse: any = Promise.resolve([]); searchMockResponse.abort = jest.fn(); -const searchMock = jest.fn().mockReturnValue({ +const searchMock = jest.fn().mockReturnValue(searchMockResponse); + +const newSearchMockResponse: any = Promise.resolve([]); +newSearchMockResponse.abort = jest.fn(); +const newSearchMock = jest.fn().mockReturnValue({ toPromise: () => searchMockResponse, }); @@ -40,6 +48,9 @@ describe('defaultSearchStrategy', function() { let searchArgs: MockedKeys>; beforeEach(() => { + msearchMockResponse.abort.mockClear(); + msearchMock.mockClear(); + searchMockResponse.abort.mockClear(); searchMock.mockClear(); @@ -51,18 +62,61 @@ describe('defaultSearchStrategy', function() { ], esShardTimeout: 0, searchService: { + search: newSearchMock, + }, + es: { + msearch: msearchMock, search: searchMock, }, }; }); - test('should call search service', () => { + test('does not send max_concurrent_shard_requests by default', async () => { + const config = getConfigStub({ 'courier:batchSearches': true }); + await search({ ...searchArgs, config }); + expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); + }); + + test('allows configuration of max_concurrent_shard_requests', async () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + 'courier:maxConcurrentShardRequests': 42, + }); + await search({ ...searchArgs, config }); + expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); + }); + + test('should set rest_total_hits_as_int to true on a request', async () => { + const config = getConfigStub({ 'courier:batchSearches': true }); + await search({ ...searchArgs, config }); + expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); + }); + + test('should set ignore_throttled=false when including frozen indices', async () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + 'search:includeFrozen': true, + }); + await search({ ...searchArgs, config }); + expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); + }); + + test('should properly call abort with msearch', () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + }); + search({ ...searchArgs, config }).abort(); + expect(msearchMockResponse.abort).toHaveBeenCalled(); + }); + + test('should call new search service', () => { const config = getConfigStub(); search({ ...searchArgs, config }); - expect(searchMock).toHaveBeenCalled(); + expect(newSearchMock).toHaveBeenCalled(); + expect(searchMock).toHaveBeenCalledTimes(0); }); - test('should properly abort with search', async () => { + test('should properly abort with new search service', async () => { const abortSpy = jest.spyOn(AbortController.prototype, 'abort'); const config = getConfigStub({}); search({ ...searchArgs, config }).abort(); diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index 5f4b8ae71acf2..ea14e49ebe09f 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -19,13 +19,18 @@ import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; import { isDefaultTypeIndexPattern } from './is_default_type_index_pattern'; -import { getSearchParams } from '../fetch/get_search_params'; +import { + getSearchParams, + getMSearchParams, + getPreference, + getTimeout, +} from '../fetch/get_search_params'; export const defaultSearchStrategy: SearchStrategyProvider = { id: 'default', search: params => { - return search(params); + return params.config.get('courier:batchSearches') ? msearch(params) : search(params); }, isViable: indexPattern => { @@ -33,6 +38,37 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; +// @deprecated +function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { + const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { + const inlineHeader = { + index: index.title || index, + search_type: searchType, + ignore_unavailable: true, + preference: getPreference(config), + }; + const inlineBody = { + ...body, + timeout: getTimeout(esShardTimeout), + }; + return `${JSON.stringify(inlineHeader)}\n${JSON.stringify(inlineBody)}`; + }); + + const searching = es.msearch({ + ...getMSearchParams(config), + body: `${inlineRequests.join('\n')}\n`, + headers: { + // need to get version from context + 'kbn-version': '8.0.0', + }, + }); + + return { + searching: searching.then(({ responses }: any) => responses), + abort: searching.abort, + }; +} + function search({ searchRequests, searchService, diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index cd55048ca527f..7bad08daa891a 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -32,7 +32,13 @@ import { FieldFormatsService } from './field_formats_provider'; import { QueryService } from './query'; import { createIndexPatternSelect } from './ui/index_pattern_select'; import { IndexPatterns } from './index_patterns'; -import { setNotifications, setFieldFormats, setOverlays, setIndexPatterns } from './services'; +import { + setNotifications, + setFieldFormats, + setOverlays, + setIndexPatterns, + setHttp, +} from './services'; import { createFilterAction, GLOBAL_APPLY_FILTER_ACTION } from './actions'; import { APPLY_FILTER_TRIGGER } from '../../embeddable/public'; import { createSearchBar } from './ui/search_bar/create_search_bar'; @@ -75,6 +81,7 @@ export class DataPublicPlugin implements Plugin('Http'); + export const [getFieldFormats, setFieldFormats] = createGetterSetter( 'FieldFormats' ); From c68fcd03f32d9dc11b19045dfdd50dace4e9266c Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 8 Jan 2020 17:25:00 +0200 Subject: [PATCH 25/46] typescript fixes --- .../data/public/search/search_source/search_source.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 597dc9e63bad8..869cbf6ecb280 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -101,7 +101,7 @@ export class SearchSource { > = []; private inheritOptions: SearchSourceOptions = {}; public history: SearchRequest[] = []; - esCli: ApiCaller; + private esCli: ApiCaller; constructor(private fields: SearchSourceFields = {}) { const http = getHttp(); @@ -205,7 +205,7 @@ export class SearchSource { return this.parent; } - getEsUrl(http: CoreStart['http']) { + private getEsUrl(http: CoreStart['http']) { const a = document.createElement('a'); a.href = http.basePath.prepend('/elasticsearch'); const protocolPort = /https/.test(a.protocol) ? 443 : 80; From d0005b76a635d89296f1fc1ba4a27d9514024347 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 8 Jan 2020 18:32:39 +0200 Subject: [PATCH 26/46] set http service mock --- .../data/public/search/search_source/search_source.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts index 62475c011ff90..d1d86fd613a96 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts @@ -23,12 +23,14 @@ import { setSearchService, setUiSettings, setInjectedMetadata, + setHttp, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; import { injectedMetadataServiceMock, uiSettingsServiceMock, + httpServiceMock, } from '../../../../../../core/public/mocks'; setUiSettings(uiSettingsServiceMock.createStartContract()); @@ -36,6 +38,7 @@ setInjectedMetadata(injectedMetadataServiceMock.createSetupContract()); setSearchService({ search: jest.fn(), }); +setHttp(httpServiceMock.createStartContract()); jest.mock('../fetch', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), From d8033636f82c4318f0067ea2b313a4abc5b0ef01 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 12:37:52 +0200 Subject: [PATCH 27/46] Move es client to dat aplugin, for follow up PR --- src/legacy/core_plugins/data/public/plugin.ts | 2 + .../search/search_source/search_source.ts | 37 ++------------ .../data/public/es_client/get_es_client.ts | 51 +++++++++++++++++++ src/plugins/data/public/es_client/index.ts | 20 ++++++++ src/plugins/data/public/mocks.ts | 6 +++ src/plugins/data/public/plugin.ts | 4 ++ src/plugins/data/public/services.ts | 4 ++ src/plugins/data/public/types.ts | 3 ++ 8 files changed, 95 insertions(+), 32 deletions(-) create mode 100644 src/plugins/data/public/es_client/get_es_client.ts create mode 100644 src/plugins/data/public/es_client/index.ts diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 5329702348207..385b9f3b2d9db 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -31,6 +31,7 @@ import { setUiSettings, setInjectedMetadata, setHttp, + setEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; @@ -76,6 +77,7 @@ export class DataPlugin setFieldFormats(data.fieldFormats); setQueryService(data.query); setSearchService(data.search); + setEsClient(data.__LEGACY.esClient); setIndexPatterns(data.indexPatterns); setFieldFormats(data.fieldFormats); setNotifications(core.notifications); diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 869cbf6ecb280..c908ecbb9a561 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -72,7 +72,6 @@ // @ts-ignore import { default as es } from 'elasticsearch-browser/elasticsearch'; import _ from 'lodash'; -import { CoreStart } from 'kibana/public'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -80,13 +79,13 @@ import { getHighlightRequest, esFilters, esQuery } from '../../../../../../plugi import { RequestFailure } from '../fetch/errors'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { SearchSourceOptions, SearchSourceFields, SearchRequest } from './types'; -import { FetchOptions, ApiCaller } from '../fetch/types'; +import { FetchOptions } from '../fetch/types'; import { getSearchService, getUiSettings, getInjectedMetadata, - getHttp, + getEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; @@ -101,21 +100,8 @@ export class SearchSource { > = []; private inheritOptions: SearchSourceOptions = {}; public history: SearchRequest[] = []; - private esCli: ApiCaller; - - constructor(private fields: SearchSourceFields = {}) { - const http = getHttp(); - const esRequestTimeout = getInjectedMetadata().getInjectedVar('esRequestTimeout') as number; - const esApiVersion = getInjectedMetadata().getInjectedVar('esApiVersion') as string; - - // Use legacy es client for msearch. - this.esCli = es.Client({ - host: this.getEsUrl(http), - log: 'info', - requestTimeout: esRequestTimeout, - apiVersion: esApiVersion, - }); - } + + constructor(private fields: SearchSourceFields = {}) {} /** *** * PUBLIC API @@ -205,19 +191,6 @@ export class SearchSource { return this.parent; } - private getEsUrl(http: CoreStart['http']) { - const a = document.createElement('a'); - a.href = http.basePath.prepend('/elasticsearch'); - const protocolPort = /https/.test(a.protocol) ? 443 : 80; - const port = a.port || protocolPort; - return { - host: a.hostname, - port, - protocol: a.protocol, - pathname: a.pathname, - }; - } - /** * Fetch this source and reject the returned Promise on error * @@ -240,7 +213,7 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout, es: this.esCli } + { searchService, config, esShardTimeout, es: getEsClient() } ); if (response.error) { diff --git a/src/plugins/data/public/es_client/get_es_client.ts b/src/plugins/data/public/es_client/get_es_client.ts new file mode 100644 index 0000000000000..3b4ca4d3aa958 --- /dev/null +++ b/src/plugins/data/public/es_client/get_es_client.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ + +// @ts-ignore +import { default as es } from 'elasticsearch-browser/elasticsearch'; +import { CoreStart } from 'kibana/public'; + +export function getEsClient( + injectedMetadata: CoreStart['injectedMetadata'], + http: CoreStart['http'] +) { + const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; + const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; + + // Use legacy es client for msearch. + return es.Client({ + host: getEsUrl(http), + log: 'info', + requestTimeout: esRequestTimeout, + apiVersion: esApiVersion, + }); +} + +function getEsUrl(http: CoreStart['http']) { + const a = document.createElement('a'); + a.href = http.basePath.prepend('/elasticsearch'); + const protocolPort = /https/.test(a.protocol) ? 443 : 80; + const port = a.port || protocolPort; + return { + host: a.hostname, + port, + protocol: a.protocol, + pathname: a.pathname, + }; +} diff --git a/src/plugins/data/public/es_client/index.ts b/src/plugins/data/public/es_client/index.ts new file mode 100644 index 0000000000000..bf1a3f5d6e7c4 --- /dev/null +++ b/src/plugins/data/public/es_client/index.ts @@ -0,0 +1,20 @@ +/* + * 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 { getEsClient } from './get_es_client'; diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 03d3dad61ed05..87b0573ecd4d9 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -76,6 +76,12 @@ const createStartContract = (): Start => { IndexPatternSelect: jest.fn(), SearchBar: jest.fn(), }, + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, indexPatterns: {} as IndexPatternsContract, }; return startContract; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 7bad08daa891a..e74530e0b12c9 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -42,6 +42,7 @@ import { import { createFilterAction, GLOBAL_APPLY_FILTER_ACTION } from './actions'; import { APPLY_FILTER_TRIGGER } from '../../embeddable/public'; import { createSearchBar } from './ui/search_bar/create_search_bar'; +import { getEsClient } from './es_client'; export class DataPublicPlugin implements Plugin { private readonly autocomplete = new AutocompleteProviderRegister(); @@ -95,6 +96,9 @@ export class DataPublicPlugin implements Plugin('Search'); + +export const [getEsClient, setEsClient] = createGetterSetter< + DataPublicPluginStart['__LEGACY']['esClient'] +>('EsClient'); diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 4fd8bdbaae7b8..0815e599a57ce 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -51,6 +51,9 @@ export interface DataPublicPluginStart { search: ISearchStart; fieldFormats: FieldFormatsStart; query: QueryStart; + __LEGACY: { + esClient: any; + }; ui: { IndexPatternSelect: React.ComponentType; SearchBar: React.ComponentType; From 917b91ae30b3675c2e331d4237a0cddafa857781 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 13:13:27 +0200 Subject: [PATCH 28/46] Add karma mock --- .../ui/public/new_platform/new_platform.karma_mock.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 06424ea48a40f..bda4afb62fc30 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -232,6 +232,12 @@ export const npStart = { }, history: sinon.fake(), }, + __LEGACY: { + esClient: { + search: sinon.fake(), + msearch: sinon.fake(), + }, + }, }, fieldFormats: getFieldFormatsRegistry(mockCore), }, From c2f375a965973c0a0df9a1238e2aff00e3cbfacb Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 14:26:34 +0200 Subject: [PATCH 29/46] krma mock --- .../public/new_platform/new_platform.karma_mock.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index bda4afb62fc30..3db7795b75f51 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -180,6 +180,12 @@ export const npStart = { IndexPatternSelect: mockComponent, SearchBar: mockComponent, }, + __LEGACY: { + esClient: { + search: sinon.fake(), + msearch: sinon.fake(), + }, + }, query: { filterManager: { getFetches$: sinon.fake(), @@ -232,12 +238,6 @@ export const npStart = { }, history: sinon.fake(), }, - __LEGACY: { - esClient: { - search: sinon.fake(), - msearch: sinon.fake(), - }, - }, }, fieldFormats: getFieldFormatsRegistry(mockCore), }, From 96040303e7e5ecbf0bc18403d4f84dab29d9b440 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 17:45:28 +0200 Subject: [PATCH 30/46] fix tests --- .../search_source/search_source.test.ts | 7 ++-- .../query_string_input.test.tsx.snap | 36 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts index d1d86fd613a96..6de58d7e26762 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts @@ -23,7 +23,7 @@ import { setSearchService, setUiSettings, setInjectedMetadata, - setHttp, + setEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; @@ -38,7 +38,10 @@ setInjectedMetadata(injectedMetadataServiceMock.createSetupContract()); setSearchService({ search: jest.fn(), }); -setHttp(httpServiceMock.createStartContract()); +setEsClient({ + search: jest.fn(), + msearch: jest.fn(), +}); jest.mock('../fetch', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), diff --git a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap index 2fce33793cd46..96ccc12d2cd32 100644 --- a/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap +++ b/src/plugins/data/public/ui/query_string_input/__snapshots__/query_string_input.test.tsx.snap @@ -150,6 +150,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], @@ -769,6 +775,12 @@ exports[`QueryStringInput Should disable autoFocus on EuiFieldText when disableA "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], @@ -1376,6 +1388,12 @@ exports[`QueryStringInput Should pass the query language to the language switche "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], @@ -1992,6 +2010,12 @@ exports[`QueryStringInput Should pass the query language to the language switche "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], @@ -2599,6 +2623,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], @@ -3215,6 +3245,12 @@ exports[`QueryStringInput Should render the given query 1`] = ` "setIsVisible": [MockFunction], }, "data": Object { + "__LEGACY": Object { + "esClient": Object { + "msearch": [MockFunction], + "search": [MockFunction], + }, + }, "autocomplete": Object { "addProvider": [MockFunction], "clearProviders": [MockFunction], From 9ff4373db2dc54a49328e7593a9c35b9cbe69bcb Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 18:33:45 +0200 Subject: [PATCH 31/46] ts --- .../data/public/search/search_source/search_source.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts index 6de58d7e26762..4e3a9406aeb9e 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts @@ -30,7 +30,6 @@ import { import { injectedMetadataServiceMock, uiSettingsServiceMock, - httpServiceMock, } from '../../../../../../core/public/mocks'; setUiSettings(uiSettingsServiceMock.createStartContract()); From 95ebf0948c268b8fcc1a3985a027e540188b9802 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 19:44:14 +0200 Subject: [PATCH 32/46] Pass in version dynamically --- .../core_plugins/data/public/search/fetch/types.ts | 1 + .../data/public/search/search_source/search_source.ts | 7 +++++-- .../search/search_strategy/default_search_strategy.ts | 11 ++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts index cb845ff7d2b84..391ceb3bd5c44 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/types.ts @@ -44,4 +44,5 @@ export interface FetchHandlers { searchService: ISearchStart; config: IUiSettingsClient; esShardTimeout: number; + version: string; } diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index c908ecbb9a561..422c3bbb99c33 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -72,6 +72,7 @@ // @ts-ignore import { default as es } from 'elasticsearch-browser/elasticsearch'; import _ from 'lodash'; +import { npSetup } from 'ui/new_platform'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -89,6 +90,8 @@ import { // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; +// TODO: While moving to NP, replace with initializerContext + export type ISearchSource = Pick; export class SearchSource { @@ -206,14 +209,14 @@ export class SearchSource { this.history = [searchRequest]; const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number; - + const { version } = npSetup.core.injectedMetadata.getLegacyMetadata(); const response = await fetchSoon( searchRequest, { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout, es: getEsClient() } + { searchService, config, esShardTimeout, version, es: getEsClient() } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index ea14e49ebe09f..2e27e1088c836 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -39,7 +39,13 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }; // @deprecated -function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { +function msearch({ + searchRequests, + es, + config, + version, + esShardTimeout, +}: SearchStrategySearchParams) { const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { const inlineHeader = { index: index.title || index, @@ -58,8 +64,7 @@ function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategyS ...getMSearchParams(config), body: `${inlineRequests.join('\n')}\n`, headers: { - // need to get version from context - 'kbn-version': '8.0.0', + 'kbn-version': version, }, }); From 14e2842e36bb457d7125959af4028cdda35bd1dc Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 9 Jan 2020 23:08:49 +0200 Subject: [PATCH 33/46] add headers to esClient host --- .../core_plugins/data/public/search/fetch/types.ts | 1 - .../public/search/search_source/search_source.ts | 4 +--- .../search_strategy/default_search_strategy.ts | 11 +---------- src/plugins/data/public/es_client/get_es_client.ts | 12 ++++++++---- src/plugins/data/public/plugin.ts | 12 ++++++++++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts index 391ceb3bd5c44..cb845ff7d2b84 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/types.ts @@ -44,5 +44,4 @@ export interface FetchHandlers { searchService: ISearchStart; config: IUiSettingsClient; esShardTimeout: number; - version: string; } diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 422c3bbb99c33..5ca8ffa4c0503 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -72,7 +72,6 @@ // @ts-ignore import { default as es } from 'elasticsearch-browser/elasticsearch'; import _ from 'lodash'; -import { npSetup } from 'ui/new_platform'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; import { fieldWildcardFilter } from '../../../../../../plugins/kibana_utils/public'; @@ -209,14 +208,13 @@ export class SearchSource { this.history = [searchRequest]; const esShardTimeout = getInjectedMetadata().getInjectedVar('esShardTimeout') as number; - const { version } = npSetup.core.injectedMetadata.getLegacyMetadata(); const response = await fetchSoon( searchRequest, { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout, version, es: getEsClient() } + { searchService, config, esShardTimeout, es: getEsClient() } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index 2e27e1088c836..a83bd93a02796 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -39,13 +39,7 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }; // @deprecated -function msearch({ - searchRequests, - es, - config, - version, - esShardTimeout, -}: SearchStrategySearchParams) { +function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { const inlineHeader = { index: index.title || index, @@ -63,9 +57,6 @@ function msearch({ const searching = es.msearch({ ...getMSearchParams(config), body: `${inlineRequests.join('\n')}\n`, - headers: { - 'kbn-version': version, - }, }); return { diff --git a/src/plugins/data/public/es_client/get_es_client.ts b/src/plugins/data/public/es_client/get_es_client.ts index 3b4ca4d3aa958..9ec505f30b5bb 100644 --- a/src/plugins/data/public/es_client/get_es_client.ts +++ b/src/plugins/data/public/es_client/get_es_client.ts @@ -19,25 +19,26 @@ // @ts-ignore import { default as es } from 'elasticsearch-browser/elasticsearch'; -import { CoreStart } from 'kibana/public'; +import { CoreStart, PackageInfo } from 'kibana/public'; export function getEsClient( injectedMetadata: CoreStart['injectedMetadata'], - http: CoreStart['http'] + http: CoreStart['http'], + packageInfo: PackageInfo ) { const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; // Use legacy es client for msearch. return es.Client({ - host: getEsUrl(http), + host: getEsUrl(http, packageInfo), log: 'info', requestTimeout: esRequestTimeout, apiVersion: esApiVersion, }); } -function getEsUrl(http: CoreStart['http']) { +function getEsUrl(http: CoreStart['http'], packageInfo: PackageInfo) { const a = document.createElement('a'); a.href = http.basePath.prepend('/elasticsearch'); const protocolPort = /https/.test(a.protocol) ? 443 : 80; @@ -47,5 +48,8 @@ function getEsUrl(http: CoreStart['http']) { port, protocol: a.protocol, pathname: a.pathname, + headers: { + 'kbn-version': packageInfo.version, + }, }; } diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index e74530e0b12c9..5ba2c41abc6a4 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -17,7 +17,13 @@ * under the License. */ -import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { + PluginInitializerContext, + CoreSetup, + CoreStart, + Plugin, + PackageInfo, +} from 'src/core/public'; import { Storage, IStorageWrapper } from '../../kibana_utils/public'; import { DataPublicPluginSetup, @@ -50,12 +56,14 @@ export class DataPublicPlugin implements Plugin Date: Sun, 12 Jan 2020 11:57:13 +0200 Subject: [PATCH 34/46] Restored fetch soon test Use tap for loadingCount side effects --- .../public/search/fetch/fetch_soon.test.ts | 16 ++++++++++++++++ .../search/create_app_mount_context_search.ts | 18 +++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts index 960ef90559fa5..69a343c78b1e1 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/fetch_soon.test.ts @@ -72,6 +72,22 @@ describe('fetchSoon', () => { expect(callClient).toBeCalled(); }); + test('should delay by 50ms if config is set to batch searches', () => { + const config = getConfigStub({ + 'courier:batchSearches': true, + }); + const request = {}; + const options = {}; + + fetchSoon(request, options, { config } as FetchHandlers); + + expect(callClient).not.toBeCalled(); + jest.advanceTimersByTime(0); + expect(callClient).not.toBeCalled(); + jest.advanceTimersByTime(50); + expect(callClient).toBeCalled(); + }); + test('should send a batch of requests to callClient', () => { const config = getConfigStub({ 'courier:batchSearches': true, diff --git a/src/plugins/data/public/search/create_app_mount_context_search.ts b/src/plugins/data/public/search/create_app_mount_context_search.ts index ea95b63778074..f480b8f3e042e 100644 --- a/src/plugins/data/public/search/create_app_mount_context_search.ts +++ b/src/plugins/data/public/search/create_app_mount_context_search.ts @@ -17,7 +17,7 @@ * under the License. */ -import { mergeMap } from 'rxjs/operators'; +import { mergeMap, tap } from 'rxjs/operators'; import { from, BehaviorSubject } from 'rxjs'; import { ISearchAppMountContext } from './i_search_app_mount_context'; import { ISearchGeneric } from './i_search'; @@ -50,16 +50,12 @@ export const createAppMountSearchContext = ( return from(strategyPromise).pipe( mergeMap(strategy => { loadingCount$.next(loadingCount$.getValue() + 1); - const search$ = strategy.search(request, options); - search$.subscribe({ - error: () => { - loadingCount$.next(loadingCount$.getValue() - 1); - }, - complete: () => { - loadingCount$.next(loadingCount$.getValue() - 1); - }, - }); - return search$; + return strategy.search(request, options).pipe( + tap( + error => loadingCount$.next(loadingCount$.getValue() - 1), + complete => loadingCount$.next(loadingCount$.getValue() - 1) + ) + ); }) ); }; From ca9dea01d59fddd10b43513450707421248b96d5 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 12 Jan 2020 12:28:24 +0200 Subject: [PATCH 35/46] Cleanup search params --- .../data/public/search/fetch/get_search_params.ts | 6 +----- .../search/search_strategy/default_search_strategy.ts | 9 ++------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts index de9ec4cb920e8..ec97cb6b7ee45 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts @@ -29,14 +29,10 @@ export function getMSearchParams(config: IUiSettingsClient) { }; } -export function getSearchParams(config: IUiSettingsClient, esShardTimeout: number = 0) { +export function getSearchParams(config: IUiSettingsClient) { return { - rest_total_hits_as_int: true, - ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(config), max_concurrent_shard_requests: getMaxConcurrentShardRequests(config), - preference: getPreference(config), - timeout: getTimeout(esShardTimeout), }; } diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index a83bd93a02796..b5973c28f12eb 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -65,14 +65,9 @@ function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategyS }; } -function search({ - searchRequests, - searchService, - config, - esShardTimeout, -}: SearchStrategySearchParams) { +function search({ searchRequests, searchService, config }: SearchStrategySearchParams) { const abortController = new AbortController(); - const searchParams = getSearchParams(config, esShardTimeout); + const searchParams = getSearchParams(config); const promises = searchRequests.map(({ index, body }) => { const params = { index: index.title || index, From 30b94786122181f41ac44606899655ed85c0dc52 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 12 Jan 2020 13:03:34 +0200 Subject: [PATCH 36/46] Cleanup search params test --- .../search/fetch/get_search_params.test.ts | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts index f856aa77bf1f8..69a2b8824527b 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts @@ -66,18 +66,6 @@ describe('getMSearchParams', () => { }); describe('getSearchParams', () => { - test('includes rest_total_hits_as_int', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.rest_total_hits_as_int).toBe(true); - }); - - test('includes ignore_unavailable', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.ignore_unavailable).toBe(true); - }); - test('includes ignore_throttled according to search:includeFrozen', () => { let config = getConfigStub({ 'search:includeFrozen': true }); let searchParams = getSearchParams(config); @@ -97,13 +85,4 @@ describe('getSearchParams', () => { searchParams = getSearchParams(config); expect(searchParams.max_concurrent_shard_requests).toBe(5); }); - - test('includes timeout according to esShardTimeout if greater than 0', () => { - const config = getConfigStub(); - let searchParams = getSearchParams(config, 0); - expect(searchParams.timeout).toBe(undefined); - - searchParams = getSearchParams(config, 100); - expect(searchParams.timeout).toBe('100ms'); - }); }); From e849b2cfa38f821c3aed0fde94f3db8b63888e1f Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 13 Jan 2020 18:38:35 +0200 Subject: [PATCH 37/46] Revert "Cleanup search params" This reverts commit ca9dea01d59fddd10b43513450707421248b96d5. --- .../data/public/search/fetch/get_search_params.ts | 6 +++++- .../search/search_strategy/default_search_strategy.ts | 9 +++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts index ec97cb6b7ee45..de9ec4cb920e8 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.ts @@ -29,10 +29,14 @@ export function getMSearchParams(config: IUiSettingsClient) { }; } -export function getSearchParams(config: IUiSettingsClient) { +export function getSearchParams(config: IUiSettingsClient, esShardTimeout: number = 0) { return { + rest_total_hits_as_int: true, + ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(config), max_concurrent_shard_requests: getMaxConcurrentShardRequests(config), + preference: getPreference(config), + timeout: getTimeout(esShardTimeout), }; } diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index b5973c28f12eb..a83bd93a02796 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -65,9 +65,14 @@ function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategyS }; } -function search({ searchRequests, searchService, config }: SearchStrategySearchParams) { +function search({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { const abortController = new AbortController(); - const searchParams = getSearchParams(config); + const searchParams = getSearchParams(config, esShardTimeout); const promises = searchRequests.map(({ index, body }) => { const params = { index: index.title || index, From 3ff6d3c31fef4c336186975c435724ece006ba2b Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 13 Jan 2020 18:38:53 +0200 Subject: [PATCH 38/46] Revert "Cleanup search params test" This reverts commit 30b94786122181f41ac44606899655ed85c0dc52. --- .../search/fetch/get_search_params.test.ts | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts index 69a2b8824527b..f856aa77bf1f8 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/get_search_params.test.ts @@ -66,6 +66,18 @@ describe('getMSearchParams', () => { }); describe('getSearchParams', () => { + test('includes rest_total_hits_as_int', () => { + const config = getConfigStub(); + const searchParams = getSearchParams(config); + expect(searchParams.rest_total_hits_as_int).toBe(true); + }); + + test('includes ignore_unavailable', () => { + const config = getConfigStub(); + const searchParams = getSearchParams(config); + expect(searchParams.ignore_unavailable).toBe(true); + }); + test('includes ignore_throttled according to search:includeFrozen', () => { let config = getConfigStub({ 'search:includeFrozen': true }); let searchParams = getSearchParams(config); @@ -85,4 +97,13 @@ describe('getSearchParams', () => { searchParams = getSearchParams(config); expect(searchParams.max_concurrent_shard_requests).toBe(5); }); + + test('includes timeout according to esShardTimeout if greater than 0', () => { + const config = getConfigStub(); + let searchParams = getSearchParams(config, 0); + expect(searchParams.timeout).toBe(undefined); + + searchParams = getSearchParams(config, 100); + expect(searchParams.timeout).toBe('100ms'); + }); }); From 60393a2e6b1d4601f31e3ed37b14576406af8145 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 13 Jan 2020 19:02:30 +0200 Subject: [PATCH 39/46] Revert code to use old es client until #44302 is resolved --- .../default_search_strategy.ts | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index a83bd93a02796..550e5028e4b58 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -65,25 +65,26 @@ function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategyS }; } -function search({ - searchRequests, - searchService, - config, - esShardTimeout, -}: SearchStrategySearchParams) { +function search({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { const abortController = new AbortController(); const searchParams = getSearchParams(config, esShardTimeout); const promises = searchRequests.map(({ index, body }) => { - const params = { - index: index.title || index, - body, - ...searchParams, - }; - const { signal } = abortController; - return searchService - .search({ params }, { signal }) - .toPromise() - .then(({ rawResponse }) => rawResponse); + const searching = es.search({ index: index.title || index, body, ...searchParams }); + abortController.signal.addEventListener('abort', searching.abort); + return searching.catch(({ response }) => JSON.parse(response)); + /* + * Once #44302 is resolved, replace the old implementation with this one - + * const params = { + * index: index.title || index, + * body, + * ...searchParams, + * }; + * const { signal } = abortController; + * return searchService + * .search({ params }, { signal }) + * .toPromise() + * .then(({ rawResponse }) => rawResponse); + */ }); return { searching: Promise.all(promises), From f94aaa7316d32d26c8f15d12ba6f97d79f000830 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 13 Jan 2020 19:11:10 +0200 Subject: [PATCH 40/46] Revert changes to getPainlessError --- .../public/discover/np_ready/angular/get_painless_error.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts index 100d9cdac133b..2bbeea9d675c7 100644 --- a/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts +++ b/src/legacy/core_plugins/kibana/public/discover/np_ready/angular/get_painless_error.ts @@ -23,9 +23,9 @@ import { get } from 'lodash'; export function getPainlessError(error: Error) { const rootCause: Array<{ lang: string; script: string }> | undefined = get( error, - 'body.attributes.error.root_cause' + 'resp.error.root_cause' ); - const message: string = get(error, 'body.message'); + const message: string = get(error, 'message'); if (!rootCause) { return; From defd7876371cb5ea3d48b8ed95a5b220d7d55b81 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 13 Jan 2020 20:12:22 +0200 Subject: [PATCH 41/46] Fix jest test --- .../search/search_strategy/default_search_strategy.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index 8d70943a404a4..6212e468c4e3c 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -112,8 +112,8 @@ describe('defaultSearchStrategy', function() { test('should call new search service', () => { const config = getConfigStub(); search({ ...searchArgs, config }); - expect(newSearchMock).toHaveBeenCalled(); - expect(searchMock).toHaveBeenCalledTimes(0); + expect(searchMock).toHaveBeenCalled(); + expect(newSearchMock).toHaveBeenCalledTimes(0); }); test('should properly abort with new search service', async () => { From be0a9c6ad6ab70264991d414a462e52510b2e82d Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 15 Jan 2020 19:14:12 +0200 Subject: [PATCH 42/46] Refactor esClient to trigger loadingIndicator --- src/legacy/core_plugins/data/public/plugin.ts | 2 +- src/plugins/data/public/plugin.ts | 6 +-- .../{ => search}/es_client/get_es_client.ts | 42 ++++++++++++++++++- .../public/{ => search}/es_client/index.ts | 0 .../data/public/search/search_service.ts | 14 ++++++- src/plugins/data/public/types.ts | 3 -- 6 files changed, 54 insertions(+), 13 deletions(-) rename src/plugins/data/public/{ => search}/es_client/get_es_client.ts (58%) rename src/plugins/data/public/{ => search}/es_client/index.ts (100%) diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 385b9f3b2d9db..2278bf90fbb01 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -77,7 +77,7 @@ export class DataPlugin setFieldFormats(data.fieldFormats); setQueryService(data.query); setSearchService(data.search); - setEsClient(data.__LEGACY.esClient); + setEsClient(data.search.__LEGACY.esClient); setIndexPatterns(data.indexPatterns); setFieldFormats(data.fieldFormats); setNotifications(core.notifications); diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 5ba2c41abc6a4..3375d9491ea78 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -48,7 +48,6 @@ import { import { createFilterAction, GLOBAL_APPLY_FILTER_ACTION } from './actions'; import { APPLY_FILTER_TRIGGER } from '../../embeddable/public'; import { createSearchBar } from './ui/search_bar/create_search_bar'; -import { getEsClient } from './es_client'; export class DataPublicPlugin implements Plugin { private readonly autocomplete = new AutocompleteProviderRegister(); @@ -100,13 +99,10 @@ export class DataPublicPlugin implements Plugin ) { const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; // Use legacy es client for msearch. - return es.Client({ + const client = es.Client({ host: getEsUrl(http, packageInfo), log: 'info', requestTimeout: esRequestTimeout, apiVersion: esApiVersion, }); + + return { + search: wrapEsClientMethod(client, 'search', loadingCount$), + msearch: wrapEsClientMethod(client, 'msearch', loadingCount$), + create: wrapEsClientMethod(client, 'create', loadingCount$), + }; +} + +function wrapEsClientMethod(esClient: any, method: string, loadingCount$: BehaviorSubject) { + return (args: any) => { + // esClient returns a promise, with an additional abort handler + // To tap into the abort handling, we have to override that abort handler. + const customPromiseThingy = esClient[method](args); + const { abort } = customPromiseThingy; + let resolved = false; + + // Start LoadingIndicator + loadingCount$.next(loadingCount$.getValue() + 1); + + // Stop LoadingIndicator when user aborts + customPromiseThingy.abort = () => { + abort(); + if (!resolved) { + resolved = true; + loadingCount$.next(loadingCount$.getValue() - 1); + } + }; + + // Stop LoadingIndicator when promise finishes + customPromiseThingy.finally(() => { + resolved = true; + loadingCount$.next(loadingCount$.getValue() - 1); + }); + + return customPromiseThingy; + }; } function getEsUrl(http: CoreStart['http'], packageInfo: PackageInfo) { diff --git a/src/plugins/data/public/es_client/index.ts b/src/plugins/data/public/search/es_client/index.ts similarity index 100% rename from src/plugins/data/public/es_client/index.ts rename to src/plugins/data/public/search/es_client/index.ts diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 4144b146d1a4a..6f3e228939d6d 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -24,6 +24,7 @@ import { CoreStart, IContextContainer, PluginOpaqueId, + PackageInfo, } from '../../../../core/public'; import { ISearchAppMountContext } from './i_search_app_mount_context'; @@ -38,6 +39,7 @@ import { import { TStrategyTypes } from './strategy_types'; import { esSearchService } from './es_search'; import { ISearchGeneric } from './i_search'; +import { getEsClient } from './es_client'; /** * Extends the AppMountContext so other plugins have access @@ -51,6 +53,9 @@ declare module 'kibana/public' { export interface ISearchStart { search: ISearchGeneric; + __LEGACY: { + esClient: any; + }; } /** @@ -121,11 +126,16 @@ export class SearchService implements Plugin { return api; } - public start(core: CoreStart) { + public start(core: CoreStart, packageInfo: PackageInfo) { if (!this.search) { throw new Error('Search should always be defined'); } - return { search: this.search }; + return { + search: this.search, + __LEGACY: { + esClient: getEsClient(core.injectedMetadata, core.http, packageInfo, this.loadingCount$), + }, + }; } public stop() {} diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 0815e599a57ce..4fd8bdbaae7b8 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -51,9 +51,6 @@ export interface DataPublicPluginStart { search: ISearchStart; fieldFormats: FieldFormatsStart; query: QueryStart; - __LEGACY: { - esClient: any; - }; ui: { IndexPatternSelect: React.ComponentType; SearchBar: React.ComponentType; From aa0506aacbd8f7d5582389bf893b0090045e1478 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 16 Jan 2020 00:47:52 +0200 Subject: [PATCH 43/46] fixing tests --- src/legacy/core_plugins/data/public/plugin.ts | 2 -- .../search/search_source/search_source.test.ts | 11 ++++++----- .../public/search/search_source/search_source.ts | 3 +-- .../default_search_strategy.test.ts | 6 ++++++ .../public/new_platform/new_platform.karma_mock.js | 14 ++++++++------ src/plugins/data/public/mocks.ts | 11 ++++++++++- src/plugins/data/public/services.ts | 4 ---- 7 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/legacy/core_plugins/data/public/plugin.ts b/src/legacy/core_plugins/data/public/plugin.ts index 2278bf90fbb01..5329702348207 100644 --- a/src/legacy/core_plugins/data/public/plugin.ts +++ b/src/legacy/core_plugins/data/public/plugin.ts @@ -31,7 +31,6 @@ import { setUiSettings, setInjectedMetadata, setHttp, - setEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../plugins/data/public/services'; @@ -77,7 +76,6 @@ export class DataPlugin setFieldFormats(data.fieldFormats); setQueryService(data.query); setSearchService(data.search); - setEsClient(data.search.__LEGACY.esClient); setIndexPatterns(data.indexPatterns); setFieldFormats(data.fieldFormats); setNotifications(core.notifications); diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts index 4e3a9406aeb9e..ebeee60b67c8a 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.test.ts @@ -23,7 +23,6 @@ import { setSearchService, setUiSettings, setInjectedMetadata, - setEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; @@ -36,10 +35,12 @@ setUiSettings(uiSettingsServiceMock.createStartContract()); setInjectedMetadata(injectedMetadataServiceMock.createSetupContract()); setSearchService({ search: jest.fn(), -}); -setEsClient({ - search: jest.fn(), - msearch: jest.fn(), + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, }); jest.mock('../fetch', () => ({ diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 5ca8ffa4c0503..922e49910b85a 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -85,7 +85,6 @@ import { getSearchService, getUiSettings, getInjectedMetadata, - getEsClient, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; @@ -214,7 +213,7 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout, es: getEsClient() } + { searchService, config, esShardTimeout, es: searchService.__LEGACY.esClient } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index 6212e468c4e3c..af40b0be7e317 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -63,6 +63,12 @@ describe('defaultSearchStrategy', function() { esShardTimeout: 0, searchService: { search: newSearchMock, + __LEGACY: { + esClient: { + search: {}, + msearch: {}, + }, + }, }, es: { msearch: msearchMock, diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 838ebba369fa9..dfd26bc4be039 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -183,12 +183,6 @@ export const npStart = { IndexPatternSelect: mockComponent, SearchBar: mockComponent, }, - __LEGACY: { - esClient: { - search: sinon.fake(), - msearch: sinon.fake(), - }, - }, query: { filterManager: { getFetches$: sinon.fake(), @@ -242,6 +236,14 @@ export const npStart = { history: sinon.fake(), }, }, + search: { + __LEGACY: { + esClient: { + search: sinon.fake(), + msearch: sinon.fake(), + }, + }, + }, fieldFormats: getFieldFormatsRegistry(mockCore), }, share: { diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 87b0573ecd4d9..f8367dadc0c06 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -69,7 +69,16 @@ const createStartContract = (): Start => { const startContract = { autocomplete: autocompleteMock, getSuggestions: jest.fn(), - search: { search: jest.fn() }, + search: { + search: jest.fn(), + + __LEGACY: { + esClient: { + search: jest.fn(), + msearch: jest.fn(), + }, + }, + }, fieldFormats: fieldFormatsMock as FieldFormatsStart, query: queryStartMock, ui: { diff --git a/src/plugins/data/public/services.ts b/src/plugins/data/public/services.ts index ec0f9e0c38002..6a15893f573d8 100644 --- a/src/plugins/data/public/services.ts +++ b/src/plugins/data/public/services.ts @@ -55,7 +55,3 @@ export const [getInjectedMetadata, setInjectedMetadata] = createGetterSetter< export const [getSearchService, setSearchService] = createGetterSetter< DataPublicPluginStart['search'] >('Search'); - -export const [getEsClient, setEsClient] = createGetterSetter< - DataPublicPluginStart['__LEGACY']['esClient'] ->('EsClient'); From 2ade3a6da3e512dd8bea35df3cb97f07010b9661 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 16 Jan 2020 11:55:27 +0200 Subject: [PATCH 44/46] use esClient from searchService --- .../data/public/search/fetch/types.ts | 5 ----- .../search/search_source/search_source.ts | 2 +- .../search_strategy/default_search_strategy.ts | 18 +++++++++++++++--- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/fetch/types.ts b/src/legacy/core_plugins/data/public/search/fetch/types.ts index cb845ff7d2b84..fba14119d83c3 100644 --- a/src/legacy/core_plugins/data/public/search/fetch/types.ts +++ b/src/legacy/core_plugins/data/public/search/fetch/types.ts @@ -36,11 +36,6 @@ export interface FetchOptions { } export interface FetchHandlers { - /* - * Old ApiCaller for msearch - * @deprecated - */ - es: ApiCaller; searchService: ISearchStart; config: IUiSettingsClient; esShardTimeout: number; diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index 922e49910b85a..d2151f15ac0da 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -213,7 +213,7 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout, es: searchService.__LEGACY.esClient } + { searchService, config, esShardTimeout } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts index 550e5028e4b58..39789504de0a7 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.ts @@ -39,7 +39,13 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }; // @deprecated -function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { +function msearch({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { + const es = searchService.__LEGACY.esClient; const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { const inlineHeader = { index: index.title || index, @@ -65,13 +71,19 @@ function msearch({ searchRequests, es, config, esShardTimeout }: SearchStrategyS }; } -function search({ searchRequests, es, config, esShardTimeout }: SearchStrategySearchParams) { +function search({ + searchRequests, + searchService, + config, + esShardTimeout, +}: SearchStrategySearchParams) { const abortController = new AbortController(); const searchParams = getSearchParams(config, esShardTimeout); + const es = searchService.__LEGACY.esClient; const promises = searchRequests.map(({ index, body }) => { const searching = es.search({ index: index.title || index, body, ...searchParams }); abortController.signal.addEventListener('abort', searching.abort); - return searching.catch(({ response }) => JSON.parse(response)); + return searching.catch(({ response }: any) => JSON.parse(response)); /* * Once #44302 is resolved, replace the old implementation with this one - * const params = { From 6b80ecfe0d887cba9c353d475531237d009d4629 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 16 Jan 2020 12:14:43 +0200 Subject: [PATCH 45/46] git remove comment --- .../public/search/search_source/search_source.ts | 13 +++++-------- .../default_search_strategy.test.ts | 15 +++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts index d2151f15ac0da..e977db713ebaa 100644 --- a/src/legacy/core_plugins/data/public/search/search_source/search_source.ts +++ b/src/legacy/core_plugins/data/public/search/search_source/search_source.ts @@ -69,8 +69,6 @@ * `appSearchSource`. */ -// @ts-ignore -import { default as es } from 'elasticsearch-browser/elasticsearch'; import _ from 'lodash'; import { normalizeSortRequest } from './normalize_sort_request'; import { fetchSoon } from '../fetch'; @@ -88,8 +86,6 @@ import { // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../../../../plugins/data/public/services'; -// TODO: While moving to NP, replace with initializerContext - export type ISearchSource = Pick; export class SearchSource { @@ -198,9 +194,6 @@ export class SearchSource { * @async */ async fetch(options: FetchOptions = {}) { - const searchService = getSearchService(); - const config = getUiSettings(); - await this.requestIsStarting(options); const searchRequest = await this.flatten(); @@ -213,7 +206,11 @@ export class SearchSource { ...(this.searchStrategyId && { searchStrategyId: this.searchStrategyId }), ...options, }, - { searchService, config, esShardTimeout } + { + searchService: getSearchService(), + config: getUiSettings(), + esShardTimeout, + } ); if (response.error) { diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index af40b0be7e317..d4ae263a6f43b 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -46,6 +46,7 @@ const newSearchMock = jest.fn().mockReturnValue({ describe('defaultSearchStrategy', function() { describe('search', function() { let searchArgs: MockedKeys>; + let es: any; beforeEach(() => { msearchMockResponse.abort.mockClear(); @@ -70,17 +71,15 @@ describe('defaultSearchStrategy', function() { }, }, }, - es: { - msearch: msearchMock, - search: searchMock, - }, }; + + es = searchArgs.searchService.__LEGACY.esClient; }); test('does not send max_concurrent_shard_requests by default', async () => { const config = getConfigStub({ 'courier:batchSearches': true }); await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); + expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); }); test('allows configuration of max_concurrent_shard_requests', async () => { @@ -89,13 +88,13 @@ describe('defaultSearchStrategy', function() { 'courier:maxConcurrentShardRequests': 42, }); await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); + expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); }); test('should set rest_total_hits_as_int to true on a request', async () => { const config = getConfigStub({ 'courier:batchSearches': true }); await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); + expect(es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); }); test('should set ignore_throttled=false when including frozen indices', async () => { @@ -104,7 +103,7 @@ describe('defaultSearchStrategy', function() { 'search:includeFrozen': true, }); await search({ ...searchArgs, config }); - expect(searchArgs.es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); + expect(es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); }); test('should properly call abort with msearch', () => { From 0e8c21cc0b44844e1eb3b334114d646b0fe61490 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 16 Jan 2020 15:03:06 +0200 Subject: [PATCH 46/46] fix jest --- .../search/search_strategy/default_search_strategy.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts index d4ae263a6f43b..8caf20c50cd3a 100644 --- a/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts +++ b/src/legacy/core_plugins/data/public/search/search_strategy/default_search_strategy.test.ts @@ -66,8 +66,8 @@ describe('defaultSearchStrategy', function() { search: newSearchMock, __LEGACY: { esClient: { - search: {}, - msearch: {}, + search: searchMock, + msearch: msearchMock, }, }, },