diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 2255ac536bd5..acc19339fd0c 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -17,7 +17,7 @@ * under the License. */ -import { get, memoize, trimEnd } from 'lodash'; +import { get, memoize } from 'lodash'; import { BehaviorSubject, throwError, timer, defer, from, Observable, NEVER } from 'rxjs'; import { catchError, finalize } from 'rxjs/operators'; import { PublicMethodsOf } from '@kbn/utility-types'; @@ -29,7 +29,6 @@ import { IKibanaSearchResponse, ISearchOptions, ISessionService, - ES_SEARCH_STRATEGY, } from '../../common'; import { SearchUsageCollector } from './collectors'; import { @@ -71,7 +70,7 @@ export class SearchInterceptor { * @internal */ protected application!: CoreStart['application']; - private batchedFetch?: BatchedFunc< + private batchedFetch!: BatchedFunc< { request: IKibanaSearchRequest; strategy?: string }, IKibanaSearchResponse >; @@ -139,20 +138,7 @@ export class SearchInterceptor { signal: AbortSignal, strategy?: string ): Promise { - if (this.batchedFetch) { - return this.batchedFetch({ request, strategy }, signal); - } else { - const { id, ...searchRequest } = request; - const path = trimEnd(`/internal/search/${strategy || ES_SEARCH_STRATEGY}/${id || ''}`, '/'); - const body = JSON.stringify(searchRequest); - - return this.deps.http.fetch({ - method: 'POST', - path, - body, - signal, - }); - } + return this.batchedFetch({ request, strategy }, signal); } /** diff --git a/src/plugins/data/server/search/routes/search.test.ts b/src/plugins/data/server/search/routes/search.test.ts deleted file mode 100644 index 495cb1c9ea77..000000000000 --- a/src/plugins/data/server/search/routes/search.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import type { MockedKeys } from '@kbn/utility-types/jest'; -import { from } from 'rxjs'; -import { CoreSetup, RequestHandlerContext } from 'src/core/server'; -import { coreMock, httpServerMock } from '../../../../../../src/core/server/mocks'; -import { registerSearchRoute } from './search'; -import { DataPluginStart } from '../../plugin'; - -describe('Search service', () => { - let mockCoreSetup: MockedKeys>; - - beforeEach(() => { - mockCoreSetup = coreMock.createSetup(); - }); - - it('handler calls context.search.search with the given request and strategy', async () => { - const response = { - id: 'yay', - rawResponse: { - took: 100, - timed_out: true, - _shards: { - total: 0, - successful: 0, - failed: 0, - skipped: 0, - }, - hits: { - total: 0, - max_score: 0, - hits: [], - }, - }, - }; - - const mockContext = { - search: { - search: jest.fn().mockReturnValue(from(Promise.resolve(response))), - }, - }; - - const mockBody = { id: undefined, params: {} }; - const mockParams = { strategy: 'foo' }; - const mockRequest = httpServerMock.createKibanaRequest({ - body: mockBody, - params: mockParams, - }); - const mockResponse = httpServerMock.createResponseFactory(); - - registerSearchRoute(mockCoreSetup.http.createRouter()); - - const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; - const handler = mockRouter.post.mock.calls[0][1]; - await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); - - expect(mockContext.search.search).toBeCalled(); - expect(mockContext.search.search.mock.calls[0][0]).toStrictEqual(mockBody); - expect(mockResponse.ok).toBeCalled(); - expect(mockResponse.ok.mock.calls[0][0]).toEqual({ - body: response, - }); - }); - - it('handler throws an error if the search throws an error', async () => { - const rejectedValue = from( - Promise.reject({ - message: 'oh no', - body: { - error: 'oops', - }, - }) - ); - - const mockContext = { - search: { - search: jest.fn().mockReturnValue(rejectedValue), - }, - }; - - const mockBody = { id: undefined, params: {} }; - const mockParams = { strategy: 'foo' }; - const mockRequest = httpServerMock.createKibanaRequest({ - body: mockBody, - params: mockParams, - }); - const mockResponse = httpServerMock.createResponseFactory(); - - registerSearchRoute(mockCoreSetup.http.createRouter()); - - const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; - const handler = mockRouter.post.mock.calls[0][1]; - await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); - - expect(mockContext.search.search).toBeCalled(); - expect(mockContext.search.search.mock.calls[0][0]).toStrictEqual(mockBody); - expect(mockResponse.customError).toBeCalled(); - const error: any = mockResponse.customError.mock.calls[0][0]; - expect(error.body.message).toBe('oh no'); - expect(error.body.attributes.error).toBe('oops'); - }); -}); diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 68c897757a62..8f3634751d19 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -17,60 +17,10 @@ * under the License. */ -import { first } from 'rxjs/operators'; import { schema } from '@kbn/config-schema'; import type { IRouter } from 'src/core/server'; -import { getRequestAbortedSignal } from '../../lib'; export function registerSearchRoute(router: IRouter): void { - router.post( - { - path: '/internal/search/{strategy}/{id?}', - validate: { - params: schema.object({ - strategy: schema.string(), - id: schema.maybe(schema.string()), - }), - - query: schema.object({}, { unknowns: 'allow' }), - - body: schema.object({}, { unknowns: 'allow' }), - }, - }, - async (context, request, res) => { - const searchRequest = request.body; - const { strategy, id } = request.params; - const abortSignal = getRequestAbortedSignal(request.events.aborted$); - - try { - const response = await context - .search!.search( - { ...searchRequest, id }, - { - abortSignal, - strategy, - } - ) - .pipe(first()) - .toPromise(); - - return res.ok({ - body: response, - }); - } catch (err) { - return res.customError({ - statusCode: err.statusCode || 500, - body: { - message: err.message, - attributes: { - error: err.body?.error || err.message, - }, - }, - }); - } - } - ); - router.delete( { path: '/internal/search/{strategy}/{id}', diff --git a/src/plugins/data/server/ui_settings.ts b/src/plugins/data/server/ui_settings.ts index 9393700a0e77..f5360f626ac6 100644 --- a/src/plugins/data/server/ui_settings.ts +++ b/src/plugins/data/server/ui_settings.ts @@ -267,14 +267,13 @@ export function getUiSettings(): Record> { }, [UI_SETTINGS.COURIER_BATCH_SEARCHES]: { name: i18n.translate('data.advancedSettings.courier.batchSearchesTitle', { - defaultMessage: 'Batch concurrent searches', + defaultMessage: 'Use legacy search', }), value: false, type: 'boolean', description: i18n.translate('data.advancedSettings.courier.batchSearchesText', { - defaultMessage: `When disabled, dashboard panels will load individually, and search requests will terminate when users navigate - away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, and - searches will not terminate.`, + defaultMessage: `Kibana uses a new search and batching infrastructure. + Enable this option if you prefer to fallback to the legacy synchronous behavior`, }), deprecation: { message: i18n.translate('data.advancedSettings.courier.batchSearchesTextDeprecation', {