[Search]Add EQL search strategy (#78645)

* Add EQL search strategy

Since EQL is an x-pack feature, this strategy will live in the
x-pack plugin data_enhanced.

* Refactor our test setup to minimize shared state

* Ensures that the same variable is not used for both test setup and
  test assertions
* Ensures that mocks are reinstantiated on every test

* Use explicit top-level exports

* Move async search options to a helper function

* Move our workaround to a helper function

This was repeated in five places, time to consolidate.

* Commit documentation changes

We export a few new helper functions.

* Mark our internal methods as such

Updates documentation accordingly.

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Ryland Herrick 2020-10-05 11:30:32 -05:00 committed by GitHub
parent 5f53d4f34b
commit 951034cf0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 429 additions and 52 deletions

View file

@ -214,11 +214,13 @@ export {
ISearchSetup,
ISearchStart,
toSnakeCase,
getAsyncOptions,
getDefaultSearchParams,
getShardTimeout,
getTotalLoaded,
shimHitsTotal,
usageProvider,
shimAbortSignal,
SearchUsage,
} from './search';

View file

@ -23,7 +23,13 @@ import { Observable } from 'rxjs';
import { ApiResponse } from '@elastic/elasticsearch';
import { SearchUsage } from '../collectors/usage';
import { toSnakeCase } from './to_snake_case';
import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..';
import {
ISearchStrategy,
getDefaultSearchParams,
getTotalLoaded,
getShardTimeout,
shimAbortSignal,
} from '..';
export const esSearchStrategyProvider = (
config$: Observable<SharedGlobalConfig>,
@ -52,10 +58,10 @@ export const esSearchStrategyProvider = (
});
try {
// Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297
const promise = context.core.elasticsearch.client.asCurrentUser.search(params);
if (options?.abortSignal)
options.abortSignal.addEventListener('abort', () => promise.abort());
const promise = shimAbortSignal(
context.core.elasticsearch.client.asCurrentUser.search(params),
options?.abortSignal
);
const { body: rawResponse } = (await promise) as ApiResponse<SearchResponse<any>>;
if (usage) usage.trackSuccess(rawResponse.took);

View file

@ -42,3 +42,11 @@ export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient
trackTotalHits: true,
};
}
/**
@internal
*/
export const getAsyncOptions = () => ({
waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return
keepAlive: '1m', // Extend the TTL for this search request by one minute
});

View file

@ -21,5 +21,6 @@ export { esSearchStrategyProvider } from './es_search_strategy';
export * from './get_default_search_params';
export { getTotalLoaded } from './get_total_loaded';
export * from './to_snake_case';
export { shimAbortSignal } from './shim_abort_signal';
export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common';

View file

@ -0,0 +1,55 @@
/*
* 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 { elasticsearchServiceMock } from '../../../../../core/server/mocks';
import { shimAbortSignal } from '.';
describe('shimAbortSignal', () => {
it('aborts the promise if the signal is aborted', () => {
const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({
success: true,
});
const controller = new AbortController();
shimAbortSignal(promise, controller.signal);
controller.abort();
expect(promise.abort).toHaveBeenCalled();
});
it('returns the original promise', async () => {
const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({
success: true,
});
const controller = new AbortController();
const response = await shimAbortSignal(promise, controller.signal);
expect(response).toEqual(expect.objectContaining({ body: { success: true } }));
});
it('allows the promise to be aborted manually', () => {
const promise = elasticsearchServiceMock.createSuccessTransportRequestPromise({
success: true,
});
const controller = new AbortController();
const enhancedPromise = shimAbortSignal(promise, controller.signal);
enhancedPromise.abort();
expect(promise.abort).toHaveBeenCalled();
});
});

View file

@ -0,0 +1,41 @@
/*
* 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 { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport';
/**
*
* @internal
* NOTE: Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297
* is resolved
*
* @param promise a TransportRequestPromise
* @param signal optional AbortSignal
*
* @returns a TransportRequestPromise that will be aborted if the signal is aborted
*/
export const shimAbortSignal = <T extends TransportRequestPromise<unknown>>(
promise: T,
signal: AbortSignal | undefined
): T => {
if (signal) {
signal.addEventListener('abort', () => promise.abort());
}
return promise;
};

View file

@ -25,7 +25,7 @@ import { IUiSettingsClient, IScopedClusterClient, SharedGlobalConfig } from 'src
import { MsearchRequestBody, MsearchResponse } from '../../../common/search/search_source';
import { shimHitsTotal } from './shim_hits_total';
import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..';
import { getShardTimeout, getDefaultSearchParams, toSnakeCase, shimAbortSignal } from '..';
/** @internal */
export function convertRequestBody(
@ -74,18 +74,17 @@ export function getCallMsearch(dependencies: CallMsearchDependencies) {
const body = convertRequestBody(params.body, timeout);
// Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297
const promise = esClient.asCurrentUser.msearch(
{
body,
},
{
querystring: toSnakeCase(defaultParams),
}
const promise = shimAbortSignal(
esClient.asCurrentUser.msearch(
{
body,
},
{
querystring: toSnakeCase(defaultParams),
}
),
params.signal
);
if (params.signal) {
params.signal.addEventListener('abort', () => promise.abort());
}
const response = (await promise) as ApiResponse<{ responses: Array<SearchResponse<any>> }>;
return {

View file

@ -47,6 +47,7 @@ import { SearchResponse } from 'elasticsearch';
import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common';
import { ShardsResponse } from 'elasticsearch';
import { ToastInputFields } from 'src/core/public/notifications';
import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport';
import { Type } from '@kbn/config-schema';
import { TypeOf } from '@kbn/config-schema';
import { Unit } from '@elastic/datemath';
@ -354,6 +355,12 @@ export type Filter = {
query?: any;
};
// @internal (undocumented)
export const getAsyncOptions: () => {
waitForCompletionTimeout: string;
keepAlive: string;
};
// Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@ -980,6 +987,9 @@ export interface SearchUsage {
trackSuccess(duration: number): Promise<void>;
}
// @internal
export const shimAbortSignal: <T extends TransportRequestPromise<unknown>>(promise: T, signal: AbortSignal | undefined) => T;
// @internal
export function shimHitsTotal(response: SearchResponse<any>): {
hits: {
@ -1115,19 +1125,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
// src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:226:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:226:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:226:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:226:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:228:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:229:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:238:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:239:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:252:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:228:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:230:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:231:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:251:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:254:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index_patterns/index_patterns_service.ts:50:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:78:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts

View file

@ -5,7 +5,11 @@
*/
export {
IEnhancedEsSearchRequest,
IAsyncSearchRequest,
ENHANCED_ES_SEARCH_STRATEGY,
EQL_SEARCH_STRATEGY,
EqlRequestParams,
EqlSearchStrategyRequest,
EqlSearchStrategyResponse,
IAsyncSearchRequest,
IEnhancedEsSearchRequest,
} from './search';

View file

@ -4,8 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export {
IEnhancedEsSearchRequest,
IAsyncSearchRequest,
ENHANCED_ES_SEARCH_STRATEGY,
} from './types';
export * from './types';

View file

@ -4,7 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { IEsSearchRequest } from '../../../../../src/plugins/data/common';
import { EqlSearch } from '@elastic/elasticsearch/api/requestParams';
import { ApiResponse, TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport';
import {
IEsSearchRequest,
IKibanaSearchRequest,
IKibanaSearchResponse,
} from '../../../../../src/plugins/data/common';
export const ENHANCED_ES_SEARCH_STRATEGY = 'ese';
@ -21,3 +28,13 @@ export interface IEnhancedEsSearchRequest extends IEsSearchRequest {
*/
isRollup?: boolean;
}
export const EQL_SEARCH_STRATEGY = 'eql';
export type EqlRequestParams = EqlSearch<Record<string, unknown>>;
export interface EqlSearchStrategyRequest extends IKibanaSearchRequest<EqlRequestParams> {
options?: TransportRequestOptions;
}
export type EqlSearchStrategyResponse<T = unknown> = IKibanaSearchResponse<ApiResponse<T>>;

View file

@ -11,6 +11,6 @@ export function plugin(initializerContext: PluginInitializerContext) {
return new EnhancedDataServerPlugin(initializerContext);
}
export { ENHANCED_ES_SEARCH_STRATEGY } from '../common';
export { ENHANCED_ES_SEARCH_STRATEGY, EQL_SEARCH_STRATEGY } from '../common';
export { EnhancedDataServerPlugin as Plugin };

View file

@ -16,10 +16,10 @@ import {
PluginStart as DataPluginStart,
usageProvider,
} from '../../../../src/plugins/data/server';
import { enhancedEsSearchStrategyProvider } from './search';
import { enhancedEsSearchStrategyProvider, eqlSearchStrategyProvider } from './search';
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server';
import { getUiSettings } from './ui_settings';
import { ENHANCED_ES_SEARCH_STRATEGY } from '../common';
import { ENHANCED_ES_SEARCH_STRATEGY, EQL_SEARCH_STRATEGY } from '../common';
interface SetupDependencies {
data: DataPluginSetup;
@ -47,6 +47,11 @@ export class EnhancedDataServerPlugin implements Plugin<void, void, SetupDepende
)
);
deps.data.search.registerSearchStrategy(
EQL_SEARCH_STRATEGY,
eqlSearchStrategyProvider(this.logger)
);
deps.data.__enhance({
search: {
defaultStrategy: ENHANCED_ES_SEARCH_STRATEGY,

View file

@ -0,0 +1,168 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Logger, RequestHandlerContext } from 'src/core/server';
import { EqlSearchStrategyRequest } from '../../common/search/types';
import { eqlSearchStrategyProvider } from './eql_search_strategy';
const getMockEqlResponse = () => ({
body: {
is_partial: false,
is_running: false,
took: 162,
timed_out: false,
hits: {
total: {
value: 1,
relation: 'eq',
},
sequences: [],
},
},
});
describe('EQL search strategy', () => {
let mockLogger: Logger;
beforeEach(() => {
mockLogger = ({ debug: jest.fn() } as unknown) as Logger;
});
describe('strategy interface', () => {
it('returns a strategy with a `search` function', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
expect(typeof eqlSearch.search).toBe('function');
});
it('returns a strategy with a `cancel` function', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
expect(typeof eqlSearch.cancel).toBe('function');
});
});
describe('search()', () => {
let mockEqlSearch: jest.Mock;
let mockEqlGet: jest.Mock;
let mockContext: RequestHandlerContext;
let params: Required<EqlSearchStrategyRequest>['params'];
let options: Required<EqlSearchStrategyRequest>['options'];
beforeEach(() => {
mockEqlSearch = jest.fn().mockResolvedValueOnce(getMockEqlResponse());
mockEqlGet = jest.fn().mockResolvedValueOnce(getMockEqlResponse());
mockContext = ({
core: {
uiSettings: {
client: {
get: jest.fn(),
},
},
elasticsearch: {
client: {
asCurrentUser: {
eql: {
get: mockEqlGet,
search: mockEqlSearch,
},
},
},
},
},
} as unknown) as RequestHandlerContext;
params = {
index: 'logstash-*',
body: { query: 'process where 1 == 1' },
};
options = { ignore: [400] };
});
describe('async functionality', () => {
it('performs an eql client search with params when no ID is provided', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, { options, params });
const [[request, requestOptions]] = mockEqlSearch.mock.calls;
expect(request.index).toEqual('logstash-*');
expect(request.body).toEqual(expect.objectContaining({ query: 'process where 1 == 1' }));
expect(requestOptions).toEqual(expect.objectContaining({ ignore: [400] }));
});
it('retrieves the current request if an id is provided', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, { id: 'my-search-id' });
const [[requestParams]] = mockEqlGet.mock.calls;
expect(mockEqlSearch).not.toHaveBeenCalled();
expect(requestParams).toEqual(expect.objectContaining({ id: 'my-search-id' }));
});
});
describe('arguments', () => {
it('sends along async search options', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, { options, params });
const [[request]] = mockEqlSearch.mock.calls;
expect(request).toEqual(
expect.objectContaining({
wait_for_completion_timeout: '100ms',
keep_alive: '1m',
})
);
});
it('sends along default search parameters', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, { options, params });
const [[request]] = mockEqlSearch.mock.calls;
expect(request).toEqual(
expect.objectContaining({
ignore_unavailable: true,
ignore_throttled: true,
})
);
});
it('allows search parameters to be overridden', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, {
options,
params: {
...params,
wait_for_completion_timeout: '5ms',
keep_on_completion: false,
},
});
const [[request]] = mockEqlSearch.mock.calls;
expect(request).toEqual(
expect.objectContaining({
wait_for_completion_timeout: '5ms',
keep_alive: '1m',
keep_on_completion: false,
})
);
});
it('allows search options to be overridden', async () => {
const eqlSearch = await eqlSearchStrategyProvider(mockLogger);
await eqlSearch.search(mockContext, {
options: { ...options, maxRetries: 2, ignore: [300] },
params,
});
const [[, requestOptions]] = mockEqlSearch.mock.calls;
expect(requestOptions).toEqual(
expect.objectContaining({
max_retries: 2,
ignore: [300],
})
);
});
});
});
});

View file

@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Logger } from 'kibana/server';
import { ApiResponse, TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport';
import {
getAsyncOptions,
getDefaultSearchParams,
ISearchStrategy,
toSnakeCase,
shimAbortSignal,
} from '../../../../../src/plugins/data/server';
import { EqlSearchStrategyRequest, EqlSearchStrategyResponse } from '../../common/search/types';
export const eqlSearchStrategyProvider = (
logger: Logger
): ISearchStrategy<EqlSearchStrategyRequest, EqlSearchStrategyResponse> => {
return {
cancel: async (context, id) => {
logger.debug(`_eql/delete ${id}`);
await context.core.elasticsearch.client.asCurrentUser.eql.delete({
id,
});
},
search: async (context, request, options) => {
logger.debug(`_eql/search ${JSON.stringify(request.params) || request.id}`);
let promise: TransportRequestPromise<ApiResponse>;
const eqlClient = context.core.elasticsearch.client.asCurrentUser.eql;
const uiSettingsClient = await context.core.uiSettings.client;
const asyncOptions = getAsyncOptions();
if (request.id) {
promise = eqlClient.get({
id: request.id,
...toSnakeCase(asyncOptions),
});
} else {
const { ignoreThrottled, ignoreUnavailable } = await getDefaultSearchParams(
uiSettingsClient
);
const searchParams = toSnakeCase({
ignoreThrottled,
ignoreUnavailable,
...asyncOptions,
...request.params,
});
const searchOptions = toSnakeCase({ ...request.options });
promise = eqlClient.search(
searchParams as EqlSearchStrategyRequest['params'],
searchOptions as EqlSearchStrategyRequest['options']
);
}
const rawResponse = await shimAbortSignal(promise, options?.abortSignal);
const { id, is_partial: isPartial, is_running: isRunning } = rawResponse.body;
return {
id,
isPartial,
isRunning,
rawResponse,
};
},
};
};

View file

@ -17,6 +17,8 @@ import {
getShardTimeout,
toSnakeCase,
shimHitsTotal,
getAsyncOptions,
shimAbortSignal,
} from '../../../../../src/plugins/data/server';
import { IEnhancedEsSearchRequest } from '../../common';
import {
@ -79,11 +81,7 @@ export const enhancedEsSearchStrategyProvider = (
let promise: TransportRequestPromise<any>;
const esClient = context.core.elasticsearch.client.asCurrentUser;
const uiSettingsClient = await context.core.uiSettings.client;
const asyncOptions = {
waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return
keepAlive: '1m', // Extend the TTL for this search request by one minute
};
const asyncOptions = getAsyncOptions();
// If we have an ID, then just poll for that ID, otherwise send the entire request body
if (!request.id) {
@ -102,9 +100,7 @@ export const enhancedEsSearchStrategyProvider = (
});
}
// Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297
if (options?.abortSignal) options.abortSignal.addEventListener('abort', () => promise.abort());
const esResponse = await promise;
const esResponse = await shimAbortSignal(promise, options?.abortSignal);
const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body;
return {
id,
@ -139,9 +135,7 @@ export const enhancedEsSearchStrategyProvider = (
querystring,
});
// Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297
if (options?.abortSignal) options.abortSignal.addEventListener('abort', () => promise.abort());
const esResponse = await promise;
const esResponse = await shimAbortSignal(promise, options?.abortSignal);
const response = esResponse.body as SearchResponse<any>;
return {

View file

@ -5,3 +5,4 @@
*/
export { enhancedEsSearchStrategyProvider } from './es_search_strategy';
export { eqlSearchStrategyProvider } from './eql_search_strategy';