diff --git a/examples/search_examples/public/search/app.tsx b/examples/search_examples/public/search/app.tsx index 84bc3e1cd79be..962ad910fc08d 100644 --- a/examples/search_examples/public/search/app.tsx +++ b/examples/search_examples/public/search/app.tsx @@ -29,7 +29,7 @@ import { IInspectorInfo } from '@kbn/data-plugin/common'; import { DataPublicPluginStart, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, } from '@kbn/data-plugin/public'; import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { DataView, DataViewField } from '@kbn/data-views-plugin/public'; @@ -209,7 +209,7 @@ export const SearchExamplesApp = ({ }) .subscribe({ next: (res) => { - if (isCompleteResponse(res)) { + if (!isRunningResponse(res)) { setIsLoading(false); setResponse(res); const aggResult: number | undefined = res.rawResponse.aggregations @@ -389,7 +389,7 @@ export const SearchExamplesApp = ({ .subscribe({ next: (res) => { setResponse(res); - if (isCompleteResponse(res)) { + if (!isRunningResponse(res)) { setIsLoading(false); notifications.toasts.addSuccess({ title: 'Query result', diff --git a/examples/search_examples/public/search_sessions/app.tsx b/examples/search_examples/public/search_sessions/app.tsx index 8b7c7bbcaa144..501d0b3940c2a 100644 --- a/examples/search_examples/public/search_sessions/app.tsx +++ b/examples/search_examples/public/search_sessions/app.tsx @@ -39,7 +39,7 @@ import { DataPublicPluginStart, IEsSearchRequest, IEsSearchResponse, - isCompleteResponse, + isRunningResponse, QueryState, SearchSessionState, } from '@kbn/data-plugin/public'; @@ -706,7 +706,7 @@ function doSearch( return lastValueFrom( data.search.search(req, { sessionId }).pipe( tap((res) => { - if (isCompleteResponse(res)) { + if (!isRunningResponse(res)) { const avgResult: number | undefined = res.rawResponse.aggregations ? // @ts-expect-error @elastic/elasticsearch no way to declare a type for aggregation in the search response res.rawResponse.aggregations[1]?.value ?? res.rawResponse.aggregations[2]?.value diff --git a/examples/search_examples/public/sql_search/app.tsx b/examples/search_examples/public/sql_search/app.tsx index 33406a53f9674..86580a55e714f 100644 --- a/examples/search_examples/public/sql_search/app.tsx +++ b/examples/search_examples/public/sql_search/app.tsx @@ -26,7 +26,7 @@ import { CoreStart } from '@kbn/core/public'; import { DataPublicPluginStart, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, } from '@kbn/data-plugin/public'; import { SQL_SEARCH_STRATEGY, @@ -66,7 +66,7 @@ export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDe }) .subscribe({ next: (res) => { - if (isCompleteResponse(res)) { + if (!isRunningResponse(res)) { setIsLoading(false); setResponse(res); } diff --git a/src/plugins/data/README.mdx b/src/plugins/data/README.mdx index ca1bd6fd98954..5e188553a355f 100644 --- a/src/plugins/data/README.mdx +++ b/src/plugins/data/README.mdx @@ -158,12 +158,12 @@ The `SearchSource` API is a convenient way to construct and run an Elasticsearch One benefit of using the low-level search API, is partial response support, allowing for a better and more responsive user experience. ```.ts - import { isCompleteResponse } from '../plugins/data/public'; + import { isRunningResponse } from '../plugins/data/public'; const search$ = data.search.search(request) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { // Final result search$.unsubscribe(); } else { diff --git a/src/plugins/data/common/search/poll_search.test.ts b/src/plugins/data/common/search/poll_search.test.ts index db39b5e187036..a884f1dad1558 100644 --- a/src/plugins/data/common/search/poll_search.test.ts +++ b/src/plugins/data/common/search/poll_search.test.ts @@ -10,7 +10,7 @@ import { pollSearch } from './poll_search'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; describe('pollSearch', () => { - function getMockedSearch$(resolveOnI = 1, finishWithError = false) { + function getMockedSearch$(resolveOnI = 1) { let counter = 0; return jest.fn().mockImplementation(() => { counter++; @@ -19,7 +19,7 @@ describe('pollSearch', () => { if (lastCall) { resolve({ isRunning: false, - isPartial: finishWithError, + isPartial: false, rawResponse: {}, }); } else { @@ -57,15 +57,6 @@ describe('pollSearch', () => { expect(cancelFn).toBeCalledTimes(0); }); - test('Throws Error on ES error response', async () => { - const searchFn = getMockedSearch$(2, true); - const cancelFn = jest.fn(); - const poll = pollSearch(searchFn, cancelFn).toPromise(); - await expect(poll).rejects.toThrow(Error); - expect(searchFn).toBeCalledTimes(2); - expect(cancelFn).toBeCalledTimes(0); - }); - test('Throws AbortError on empty response', async () => { const searchFn = jest.fn().mockResolvedValue(undefined); const cancelFn = jest.fn(); diff --git a/src/plugins/data/common/search/poll_search.ts b/src/plugins/data/common/search/poll_search.ts index 1a6819257ab67..8637c472adb16 100644 --- a/src/plugins/data/common/search/poll_search.ts +++ b/src/plugins/data/common/search/poll_search.ts @@ -10,7 +10,7 @@ import { from, Observable, timer, defer, fromEvent, EMPTY } from 'rxjs'; import { expand, map, switchMap, takeUntil, takeWhile, tap } from 'rxjs/operators'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; import type { IAsyncSearchOptions, IKibanaSearchResponse } from '..'; -import { isErrorResponse, isPartialResponse } from '..'; +import { isAbortResponse, isRunningResponse } from '..'; export const pollSearch = ( search: () => Promise, @@ -57,11 +57,11 @@ export const pollSearch = ( return timer(getPollInterval(elapsedTime)).pipe(switchMap(search)); }), tap((response) => { - if (isErrorResponse(response)) { - throw response ? new Error('Received partial response') : new AbortError(); + if (isAbortResponse(response)) { + throw new AbortError(); } }), - takeWhile(isPartialResponse, true), + takeWhile(isRunningResponse, true), takeUntil(aborted$) ); }); diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index f05f198451e0a..b42cb7fdf4f25 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -103,13 +103,7 @@ import { getSearchParamsFromRequest, RequestFailure } from './fetch'; import type { FetchHandlers, SearchRequest } from './fetch'; import { getRequestInspectorStats, getResponseInspectorStats } from './inspect'; -import { - getEsQueryConfig, - IKibanaSearchResponse, - isPartialResponse, - isCompleteResponse, - UI_SETTINGS, -} from '../..'; +import { getEsQueryConfig, IKibanaSearchResponse, isRunningResponse, UI_SETTINGS } from '../..'; import { AggsStart } from '../aggs'; import { extractReferences } from './extract_references'; import { @@ -546,7 +540,7 @@ export class SearchSource { // For testing timeout messages in UI, uncomment the next line // response.rawResponse.timed_out = true; return new Observable>((obs) => { - if (isPartialResponse(response)) { + if (isRunningResponse(response)) { obs.next(this.postFlightTransform(response)); } else { if (!this.hasPostFlightRequests()) { @@ -582,7 +576,7 @@ export class SearchSource { }); }), map((response) => { - if (!isCompleteResponse(response)) { + if (isRunningResponse(response)) { return response; } return onResponse(searchRequest, response, options); diff --git a/src/plugins/data/common/search/utils.test.ts b/src/plugins/data/common/search/utils.test.ts index cd8ba5340b352..e81a35fb6caeb 100644 --- a/src/plugins/data/common/search/utils.test.ts +++ b/src/plugins/data/common/search/utils.test.ts @@ -6,210 +6,42 @@ * Side Public License, v 1. */ -import { isErrorResponse, isCompleteResponse, isPartialResponse } from './utils'; +import type { IKibanaSearchResponse } from './types'; +import { isAbortResponse, isRunningResponse } from './utils'; describe('utils', () => { - describe('isErrorResponse', () => { + describe('isAbortResponse', () => { it('returns `true` if the response is undefined', () => { - const isError = isErrorResponse(); + const isError = isAbortResponse(); expect(isError).toBe(true); }); - it('returns `true` if the response is not running and partial', () => { - const isError = isErrorResponse({ - isPartial: true, - isRunning: false, - rawResponse: {}, - }); - expect(isError).toBe(true); - }); - - it('returns `false` if the response is not running and partial and contains failure details', () => { - const isError = isErrorResponse({ - isPartial: true, - isRunning: false, - rawResponse: { - took: 7, - timed_out: false, - _shards: { - total: 2, - successful: 1, - skipped: 0, - failed: 1, - failures: [ - { - shard: 0, - index: 'remote:tmp-00002', - node: '9SNgMgppT2-6UHJNXwio3g', - reason: { - type: 'script_exception', - reason: 'runtime error', - script_stack: [ - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.getFactoryForDoc(LeafDocLookup.java:148)', - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:191)', - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:32)', - "doc['bar'].value < 10", - ' ^---- HERE', - ], - script: "doc['bar'].value < 10", - lang: 'painless', - position: { - offset: 4, - start: 0, - end: 21, - }, - caused_by: { - type: 'illegal_argument_exception', - reason: 'No field found for [bar] in mapping', - }, - }, - }, - ], - }, - _clusters: { - total: 1, - successful: 1, - skipped: 0, - details: { - remote: { - status: 'partial', - indices: 'tmp-*', - took: 3, - timed_out: false, - _shards: { - total: 2, - successful: 1, - skipped: 0, - failed: 1, - }, - failures: [ - { - shard: 0, - index: 'remote:tmp-00002', - node: '9SNgMgppT2-6UHJNXwio3g', - reason: { - type: 'script_exception', - reason: 'runtime error', - script_stack: [ - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.getFactoryForDoc(LeafDocLookup.java:148)', - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:191)', - 'org.elasticsearch.server@8.10.0/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:32)', - "doc['bar'].value < 10", - ' ^---- HERE', - ], - script: "doc['bar'].value < 10", - lang: 'painless', - position: { - offset: 4, - start: 0, - end: 21, - }, - caused_by: { - type: 'illegal_argument_exception', - reason: 'No field found for [bar] in mapping', - }, - }, - }, - ], - }, - }, - }, - hits: { - total: { - value: 1, - relation: 'eq', - }, - max_score: 0, - hits: [ - { - _index: 'remote:tmp-00001', - _id: 'd8JNlYoBFqAcOBVnvdqx', - _score: 0, - _source: { - foo: 'bar', - bar: 1, - }, - }, - ], - }, - }, - }); - expect(isError).toBe(false); - }); - - it('returns `false` if the response is running and partial', () => { - const isError = isErrorResponse({ - isPartial: true, - isRunning: true, - rawResponse: {}, - }); - expect(isError).toBe(false); - }); - - it('returns `false` if the response is complete', () => { - const isError = isErrorResponse({ - isPartial: false, - isRunning: false, - rawResponse: {}, - }); - expect(isError).toBe(false); - }); - }); - - describe('isCompleteResponse', () => { - it('returns `false` if the response is undefined', () => { - const isError = isCompleteResponse(); - expect(isError).toBe(false); - }); - - it('returns `false` if the response is running and partial', () => { - const isError = isCompleteResponse({ - isPartial: true, - isRunning: true, - rawResponse: {}, - }); - expect(isError).toBe(false); - }); - - it('returns `true` if the response is complete', () => { - const isError = isCompleteResponse({ - isPartial: false, - isRunning: false, - rawResponse: {}, - }); - expect(isError).toBe(true); - }); - - it('returns `true` if the response does not indicate isRunning', () => { - const isError = isCompleteResponse({ - rawResponse: {}, - }); + it('returns `true` if rawResponse is undefined', () => { + const isError = isAbortResponse({} as unknown as IKibanaSearchResponse); expect(isError).toBe(true); }); }); - describe('isPartialResponse', () => { + describe('isRunningResponse', () => { it('returns `false` if the response is undefined', () => { - const isError = isPartialResponse(); - expect(isError).toBe(false); + const isRunning = isRunningResponse(); + expect(isRunning).toBe(false); }); - it('returns `true` if the response is running and partial', () => { - const isError = isPartialResponse({ - isPartial: true, + it('returns `true` if the response is running', () => { + const isRunning = isRunningResponse({ isRunning: true, rawResponse: {}, }); - expect(isError).toBe(true); + expect(isRunning).toBe(true); }); - it('returns `false` if the response is complete', () => { - const isError = isPartialResponse({ - isPartial: false, + it('returns `false` if the response is finished running', () => { + const isRunning = isRunningResponse({ isRunning: false, rawResponse: {}, }); - expect(isError).toBe(false); + expect(isRunning).toBe(false); }); }); }); diff --git a/src/plugins/data/common/search/utils.ts b/src/plugins/data/common/search/utils.ts index c8a6ca46e5919..a369501981328 100644 --- a/src/plugins/data/common/search/utils.ts +++ b/src/plugins/data/common/search/utils.ts @@ -10,45 +10,20 @@ import moment from 'moment-timezone'; import { AggTypesDependencies } from '..'; import type { IKibanaSearchResponse } from './types'; +// TODO - investigate if this check is still needed +// There are no documented work flows where response or rawResponse is not returned +// Leaving check to prevent breaking changes until full investigation can be completed. /** - * From https://github.com/elastic/elasticsearch/issues/55572: "When is_running is false, the query has stopped, which - * may happen due to ... the search failed, in which case is_partial is set to true to indicate that any results that - * may be included in the search response come only from a subset of the shards that the query should have hit." - * @returns true if response had an error while executing in ES + * @returns true if response is abort */ -export const isErrorResponse = (response?: IKibanaSearchResponse) => { - return ( - !response || - !response.rawResponse || - (!response.isRunning && - !!response.isPartial && - // See https://github.com/elastic/elasticsearch/pull/97731. For CCS with ccs_minimize_roundtrips=true, isPartial - // is true if the search is complete but there are shard failures. In that case, the _clusters.details section - // will have information about those failures. This will also likely be the behavior of CCS with - // ccs_minimize_roundtrips=false and non-CCS after https://github.com/elastic/elasticsearch/issues/98913 is - // resolved. - !response.rawResponse?._clusters?.details) - ); +export const isAbortResponse = (response?: IKibanaSearchResponse) => { + return !response || !response.rawResponse; }; /** - * @returns true if response is completed successfully + * @returns true if request is still running */ -export const isCompleteResponse = (response?: IKibanaSearchResponse) => { - // Some custom search strategies do not indicate whether they are still running. In this case, assume it is complete. - if (response && !response.hasOwnProperty('isRunning')) { - return true; - } - - return !isErrorResponse(response) && Boolean(response && !response.isRunning); -}; - -/** - * @returns true if request is still running an/d response contains partial results - */ -export const isPartialResponse = (response?: IKibanaSearchResponse) => { - return Boolean(response && response.isRunning && response.isPartial); -}; +export const isRunningResponse = (response?: IKibanaSearchResponse) => response?.isRunning ?? false; export const getUserTimeZone = ( getConfig: AggTypesDependencies['getConfig'], diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 108b160b3b239..e51bb8f208326 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -197,7 +197,7 @@ export type { } from './search'; export type { ISearchOptions } from '../common'; -export { isErrorResponse, isCompleteResponse, isPartialResponse } from '../common'; +export { isRunningResponse } from '../common'; // Search namespace export const search = { diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts index ebc7f2528a6de..74b4a6cda7530 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts @@ -249,29 +249,6 @@ describe('SearchInterceptor', () => { expect(error).not.toHaveBeenCalled(); }); - test('should abort if request is partial and not running (ES graceful error)', async () => { - const responses = [ - { - time: 10, - value: { - isPartial: true, - isRunning: false, - rawResponse: {}, - id: 1, - }, - }, - ]; - mockFetchImplementation(responses); - - const response = searchInterceptor.search({}); - response.subscribe({ next, error }); - - await timeTravel(10); - - expect(error).toHaveBeenCalled(); - expect(error.mock.calls[0][0]).toBeInstanceOf(Error); - }); - test('should abort on user abort', async () => { const responses = [ { @@ -1005,30 +982,6 @@ describe('SearchInterceptor', () => { expect(fetchMock).toBeCalledTimes(2); }); - test('should deliver error to all replays', async () => { - const responses = [ - { - time: 10, - value: { - isPartial: true, - isRunning: false, - rawResponse: {}, - id: 1, - }, - }, - ]; - - mockFetchImplementation(responses); - - searchInterceptor.search(basicReq, { sessionId }).subscribe({ next, error, complete }); - searchInterceptor.search(basicReq, { sessionId }).subscribe({ next, error, complete }); - await timeTravel(10); - expect(fetchMock).toBeCalledTimes(1); - expect(error).toBeCalledTimes(2); - expect(error.mock.calls[0][0].message).toEqual('Received partial response'); - expect(error.mock.calls[1][0].message).toEqual('Received partial response'); - }); - test('should ignore anything outside params when hashing', async () => { mockFetchImplementation(basicCompleteResponse); @@ -1055,6 +1008,25 @@ describe('SearchInterceptor', () => { expect(fetchMock).toBeCalledTimes(1); }); + test('should deliver error to all replays', async () => { + const responses = [ + { + time: 10, + value: {}, + }, + ]; + + mockFetchImplementation(responses); + + searchInterceptor.search(basicReq, { sessionId }).subscribe({ next, error, complete }); + searchInterceptor.search(basicReq, { sessionId }).subscribe({ next, error, complete }); + await timeTravel(10); + expect(fetchMock).toBeCalledTimes(1); + expect(error).toBeCalledTimes(2); + expect(error.mock.calls[0][0].message).toEqual('Aborted'); + expect(error.mock.calls[1][0].message).toEqual('Aborted'); + }); + test('should ignore preference when hashing', async () => { mockFetchImplementation(basicCompleteResponse); diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts index 00ed4226fea3d..87f2ffe97c034 100644 --- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts @@ -51,7 +51,7 @@ import { IAsyncSearchOptions, IKibanaSearchRequest, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, ISearchOptions, ISearchOptionsSerializable, pollSearch, @@ -312,7 +312,7 @@ export class SearchInterceptor { tap((response) => { id = response.id; - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { searchTracker?.complete(); } }), diff --git a/src/plugins/data/public/search/search_interceptor/search_response_cache.test.ts b/src/plugins/data/public/search/search_interceptor/search_response_cache.test.ts index d97d31112f699..bab49b22f5a55 100644 --- a/src/plugins/data/public/search/search_interceptor/search_response_cache.test.ts +++ b/src/plugins/data/public/search/search_interceptor/search_response_cache.test.ts @@ -120,23 +120,17 @@ describe('SearchResponseCache', () => { isPartial: true, isRunning: true, rawResponse: { - t: 1, - }, - }, - { - isPartial: true, - isRunning: false, - rawResponse: { - t: 2, + t: 'a'.repeat(1000), }, }, + {} as any, ]); cache.set('123', wrapWithAbortController(err$)); const errHandler = jest.fn(); await err$.toPromise().catch(errHandler); - expect(errHandler).toBeCalledTimes(0); + expect(errHandler).toBeCalledTimes(1); expect(cache.get('123')).toBeUndefined(); }); diff --git a/src/plugins/data/public/search/search_interceptor/search_response_cache.ts b/src/plugins/data/public/search/search_interceptor/search_response_cache.ts index 1af32afdc5e90..a9bf468f54f48 100644 --- a/src/plugins/data/public/search/search_interceptor/search_response_cache.ts +++ b/src/plugins/data/public/search/search_interceptor/search_response_cache.ts @@ -8,7 +8,7 @@ import { Observable, Subscription } from 'rxjs'; import { SearchAbortController } from './search_abort_controller'; -import { IKibanaSearchResponse, isErrorResponse } from '../../../common'; +import { IKibanaSearchResponse } from '../../../common'; interface ResponseCacheItem { response$: Observable; @@ -102,14 +102,14 @@ export class SearchResponseCache { next: (r) => { // TODO: avoid stringiying. Get the size some other way! const newSize = new Blob([JSON.stringify(r)]).size; - if (this.byteToMb(newSize) < this.maxCacheSizeMB && !isErrorResponse(r)) { + if (this.byteToMb(newSize) < this.maxCacheSizeMB) { this.setItem(key, { ...cacheItem, size: newSize, }); this.shrink(); } else { - // Single item is too large to be cached, or an error response returned. + // Single item is too large to be cached // Evict and ignore. this.deleteItem(key); } diff --git a/src/plugins/data/server/search/collectors/search/usage.ts b/src/plugins/data/server/search/collectors/search/usage.ts index fb2a9acc37009..65eafd28538e3 100644 --- a/src/plugins/data/server/search/collectors/search/usage.ts +++ b/src/plugins/data/server/search/collectors/search/usage.ts @@ -9,7 +9,7 @@ import { once, debounce } from 'lodash'; import type { CoreSetup, Logger } from '@kbn/core/server'; import type { IEsSearchResponse, ISearchOptions } from '../../../../common'; -import { isCompleteResponse } from '../../../../common'; +import { isRunningResponse } from '../../../../common'; import { CollectedUsage } from './register'; const SAVED_OBJECT_ID = 'search-telemetry'; @@ -86,7 +86,7 @@ export function searchUsageObserver( ) { return { next(response: IEsSearchResponse) { - if (isRestore || !isCompleteResponse(response)) return; + if (isRestore || isRunningResponse(response)) return; logger.debug(`trackSearchStatus:success, took:${response.rawResponse.took}`); usage?.trackSuccess(response.rawResponse.took); }, diff --git a/src/plugins/data/server/search/session/get_search_status.test.ts b/src/plugins/data/server/search/session/get_search_status.test.ts index 20fcc6935b0d6..a4b051fa8b477 100644 --- a/src/plugins/data/server/search/session/get_search_status.test.ts +++ b/src/plugins/data/server/search/session/get_search_status.test.ts @@ -19,7 +19,7 @@ describe('getSearchStatus', () => { }; }); - test('returns an error status if search is partial and not running', async () => { + test('returns a complete status if search is partial and not running', async () => { mockClient.asyncSearch.status.mockResolvedValue({ body: { is_partial: true, @@ -28,7 +28,7 @@ describe('getSearchStatus', () => { }, }); const res = await getSearchStatus(mockClient, '123'); - expect(res.status).toBe(SearchStatus.ERROR); + expect(res.status).toBe(SearchStatus.COMPLETE); }); test('returns an error status if completion_status is an error', async () => { diff --git a/src/plugins/data/server/search/session/get_search_status.ts b/src/plugins/data/server/search/session/get_search_status.ts index f9b14fefdf397..46637555fe5e2 100644 --- a/src/plugins/data/server/search/session/get_search_status.ts +++ b/src/plugins/data/server/search/session/get_search_status.ts @@ -29,7 +29,7 @@ export async function getSearchStatus( { meta: true } ); const response = apiResponse.body; - if ((response.is_partial && !response.is_running) || response.completion_status >= 400) { + if (response.completion_status >= 400) { return { status: SearchStatus.ERROR, error: i18n.translate('data.search.statusError', { @@ -37,7 +37,7 @@ export async function getSearchStatus( values: { searchId: asyncId, errorCode: response.completion_status }, }), }; - } else if (!response.is_partial && !response.is_running) { + } else if (!response.is_running) { return { status: SearchStatus.COMPLETE, error: undefined, diff --git a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts index f4cfcabf0737b..530ee16ae75b9 100644 --- a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.test.ts @@ -266,7 +266,9 @@ describe('SQL search strategy', () => { ); const esSearch = await sqlSearchStrategyProvider(mockSearchConfig, mockLogger); - await esSearch.search({ id: 'foo', params: { query: 'query' } }, {}, mockDeps).toPromise(); + esSearch.search({ id: 'foo', params: { query: 'query' } }, {}, mockDeps); + // await next tick. esSearch.search will not resolve until `is_running: false` + await new Promise((resolve) => process.nextTick(resolve)); expect(mockSqlClearCursor).not.toHaveBeenCalled(); }); diff --git a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts index c8928a343eec5..d5d1eafc5c214 100644 --- a/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/sql_search/sql_search_strategy.ts @@ -69,7 +69,7 @@ export const sqlSearchStrategyProvider = ( )); } - if (!body.is_partial && !body.is_running && body.cursor && !keepCursor) { + if (!body.is_running && body.cursor && !keepCursor) { try { await client.sql.clearCursor({ cursor: body.cursor }); } catch (error) { diff --git a/src/plugins/discover/public/application/main/utils/fetch_documents.ts b/src/plugins/discover/public/application/main/utils/fetch_documents.ts index e849b347a22ff..99e87f13558a8 100644 --- a/src/plugins/discover/public/application/main/utils/fetch_documents.ts +++ b/src/plugins/discover/public/application/main/utils/fetch_documents.ts @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { filter, map } from 'rxjs/operators'; import { lastValueFrom } from 'rxjs'; -import { isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public'; +import { isRunningResponse, ISearchSource } from '@kbn/data-plugin/public'; import { SAMPLE_SIZE_SETTING, buildDataTableRecordList } from '@kbn/discover-utils'; import type { EsHitRecord } from '@kbn/discover-utils/types'; import { getSearchResponseInterceptedWarnings } from '@kbn/search-response-warnings'; @@ -62,7 +62,7 @@ export const fetchDocuments = ( disableWarningToasts: true, }) .pipe( - filter((res) => isCompleteResponse(res)), + filter((res) => !isRunningResponse(res)), map((res) => { return buildDataTableRecordList(res.rawResponse.hits.hits as EsHitRecord[], dataView); }) diff --git a/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.ts b/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.ts index 2beed34b3d919..5bb927747e669 100644 --- a/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.ts +++ b/src/plugins/unified_histogram/public/chart/hooks/use_total_hits.ts @@ -7,7 +7,7 @@ */ import { textBasedQueryStateToAstWithValidation } from '@kbn/data-plugin/common'; -import { isCompleteResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse } from '@kbn/data-plugin/public'; import { DataView, DataViewType } from '@kbn/data-views-plugin/public'; import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; import { Datatable, isExpressionValueError } from '@kbn/expressions-plugin/common'; @@ -209,7 +209,7 @@ const fetchTotalHitsSearchSource = async ({ disableWarningToasts: true, // TODO: show warnings as a badge next to total hits number }) .pipe( - filter((res) => isCompleteResponse(res)), + filter((res) => !isRunningResponse(res)), map((res) => res.rawResponse.hits.total as number), catchError((error: Error) => of(error)) ); diff --git a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts index 8179751266e6e..eb9f7d403421a 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts +++ b/x-pack/plugins/aiops/public/components/log_categorization/use_categorize_request.ts @@ -9,7 +9,7 @@ import { useRef, useCallback, useMemo } from 'react'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { isCompleteResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse } from '@kbn/data-plugin/public'; import { useStorage } from '@kbn/ml-local-storage'; import { createCategoryRequest } from '../../../common/api/log_categorization/create_category_request'; @@ -83,7 +83,7 @@ export function useCategorizeRequest() { ) .subscribe({ next: (result) => { - if (isCompleteResponse(result)) { + if (!isRunningResponse(result)) { resolve(processCategoryResults(result, field, unwrap)); } else { // partial results diff --git a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts index a44e176c1c073..7d905fe2894ea 100644 --- a/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts +++ b/x-pack/plugins/aiops/public/hooks/use_cancellable_search.ts @@ -6,7 +6,7 @@ */ import { useCallback, useRef, useState } from 'react'; -import { type IKibanaSearchResponse, isCompleteResponse } from '@kbn/data-plugin/common'; +import { type IKibanaSearchResponse, isRunningResponse } from '@kbn/data-plugin/common'; import { tap } from 'rxjs/operators'; import { useAiopsAppContext } from './use_aiops_app_context'; @@ -31,7 +31,7 @@ export function useCancellableSearch() { ) .subscribe({ next: (result) => { - if (isCompleteResponse(result)) { + if (!isRunningResponse(result)) { setIsFetching(false); resolve(result); } else { diff --git a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_explore_table_logic.ts b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_explore_table_logic.ts index 82cddd8f74e91..5836e64599ea0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_explore_table_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/analytics/components/analytics_collection_view/analytics_collection_explore_table_logic.ts @@ -11,7 +11,7 @@ import { DataView, IKibanaSearchRequest, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, TimeRange, } from '@kbn/data-plugin/common'; @@ -415,7 +415,7 @@ export const AnalyticsCollectionExploreTableLogic = kea< KibanaLogic.values.data.search.showError(e); }, next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { const { items, totalCount } = parseResponse(response); actions.setItems(items); diff --git a/x-pack/plugins/observability_shared/public/hooks/use_es_search.ts b/x-pack/plugins/observability_shared/public/hooks/use_es_search.ts index c4fe3b050778b..43eb2596e1581 100644 --- a/x-pack/plugins/observability_shared/public/hooks/use_es_search.ts +++ b/x-pack/plugins/observability_shared/public/hooks/use_es_search.ts @@ -9,7 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { ESSearchResponse } from '@kbn/es-types'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { IInspectorInfo, isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/common'; +import { IInspectorInfo, isRunningResponse } from '@kbn/data-plugin/common'; import { getInspectResponse } from '../../common/utils/get_inspect_response'; import { useInspectorContext } from '../contexts/inspector/use_inspector_context'; import { FETCH_STATUS, useFetcher } from './use_fetcher'; @@ -42,7 +42,7 @@ export const useEsSearch = { - if (isCompleteResponse(result)) { + if (!isRunningResponse(result)) { if (addInspectorRequest) { addInspectorRequest({ data: { @@ -72,32 +72,30 @@ export const useEsSearch = { - if (isErrorResponse(err)) { - // eslint-disable-next-line no-console - console.error(err); - if (addInspectorRequest) { - addInspectorRequest({ - data: { - _inspect: [ - getInspectResponse({ - startTime, - esRequestParams: params, - esResponse: null, - esError: { originalError: err, name: err.name, message: err.message }, - esRequestStatus: 2, - operationName: name, - kibanaRequest: { - route: { - path: '/internal/bsearch', - method: 'POST', - }, - } as any, - }), - ], - }, - status: FETCH_STATUS.SUCCESS, - }); - } + // eslint-disable-next-line no-console + console.error(err); + if (addInspectorRequest) { + addInspectorRequest({ + data: { + _inspect: [ + getInspectResponse({ + startTime, + esRequestParams: params, + esResponse: null, + esError: { originalError: err, name: err.name, message: err.message }, + esRequestStatus: 2, + operationName: name, + kibanaRequest: { + route: { + path: '/internal/bsearch', + method: 'POST', + }, + } as any, + }), + ], + }, + status: FETCH_STATUS.SUCCESS, + }); } }, }); diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx index 691d0e95cb924..5a37de1a7c61c 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/use_timelines_events.tsx @@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux'; import { Subscription } from 'rxjs'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { Inspect, PaginationInputPaginated, @@ -246,7 +246,7 @@ export const useTimelineEventsHandler = ({ ) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setTimelineResponse((prevResponse) => { const newTimelineResponse = { ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts b/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts index aac311cba167f..1b46d071d244d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts +++ b/x-pack/plugins/security_solution/public/common/containers/cti/event_enrichment/api.ts @@ -9,7 +9,7 @@ import type { Observable } from 'rxjs'; import { filter } from 'rxjs/operators'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { EventEnrichmentRequestOptionsInput } from '../../../../../common/api/search_strategy'; import type { CtiEventEnrichmentStrategyResponse } from '../../../../../common/search_strategy/security_solution/cti'; import { CtiQueries } from '../../../../../common/search_strategy/security_solution/cti'; @@ -44,4 +44,4 @@ export const getEventEnrichment = ({ export const getEventEnrichmentComplete = ( props: GetEventEnrichmentProps ): Observable => - getEventEnrichment(props).pipe(filter((response) => isCompleteResponse(response))); + getEventEnrichment(props).pipe(filter((response) => !isRunningResponse(response))); diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts index 471d43c928458..acd454f85de33 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.ts @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { inputsModel } from '../../../store'; import { useKibana } from '../../../lib/kibana'; import type { @@ -77,7 +77,7 @@ export const useTimelineLastEventTime = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setTimelineLastEventTimeResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts index 51128621da177..a9ffa6049d9f9 100644 --- a/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts +++ b/x-pack/plugins/security_solution/public/common/containers/matrix_histogram/index.ts @@ -10,7 +10,7 @@ import { getOr, noop } from 'lodash/fp'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { MatrixHistogramRequestOptionsInput } from '../../../../common/api/search_strategy'; import type { MatrixHistogramQueryProps } from '../../components/matrix_histogram/types'; import type { inputsModel } from '../../store'; @@ -121,7 +121,7 @@ export const useMatrixHistogram = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { const histogramBuckets: Buckets = getOr( bucketEmpty, MatrixHistogramTypeToAggName[histogramType], diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts index b86eaaf386149..085a168a1b65d 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.test.ts @@ -102,7 +102,7 @@ describe('useSearchStrategy', () => { useSearchStrategy({ ...userSearchStrategyProps, initialResult }) ); - expect(result.current.result).toBe(initialResult); + expect(result.current.result).toEqual(initialResult); }); it('calls start with the given request', () => { @@ -278,9 +278,7 @@ describe('useSearchStrategy', () => { it('should handle search error', () => { mockResponse.mockImplementation(() => { - throw new Error( - 'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response' - ); + throw new Error('simulated search error'); }); const { result } = renderHook(() => useSearch(factoryQueryType)); diff --git a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx index 320339b0ec4df..75eb80debeb3c 100644 --- a/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/use_search_strategy/index.tsx @@ -9,7 +9,7 @@ import { noop, omit } from 'lodash/fp'; import { useCallback, useEffect, useRef, useMemo } from 'react'; import type { Observable } from 'rxjs'; import { useObservable } from '@kbn/securitysolution-hook-utils'; -import { isCompleteResponse, isErrorResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse } from '@kbn/data-plugin/public'; import { AbortError } from '@kbn/kibana-utils-plugin/common'; import * as i18n from './translations'; @@ -64,7 +64,7 @@ export const useSearch = ( abortSignal, } ) - .pipe(filter((response) => isCompleteResponse(response))); + .pipe(filter((response) => !isRunningResponse(response))); observable.subscribe({ next: (response) => { @@ -158,7 +158,7 @@ export const useSearchStrategy = ({ }, [abort]); const [formattedResult, inspect] = useMemo(() => { - if (isErrorResponse(result)) { + if (!result) { return [initialResult, EMPTY_INSPECT]; } return [ diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx index ce7fa7e01886e..417c3678fb06a 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/dns/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { NetworkKpiDnsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; @@ -86,7 +86,7 @@ export const useNetworkKpiDns = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setNetworkKpiDnsResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx index 40e238e73d56d..e675196aa0a80 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/network_events/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { NetworkKpiEventsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; @@ -90,7 +90,7 @@ export const useNetworkKpiNetworkEvents = ({ ) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setNetworkKpiNetworkEventsResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx index 5bede07b4ce2d..a94041f640d93 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/tls_handshakes/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { NetworkKpiTlsHandshakesRequestOptionsInput } from '../../../../../../common/api/search_strategy'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; @@ -89,7 +89,7 @@ export const useNetworkKpiTlsHandshakes = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setNetworkKpiTlsHandshakesResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx index 8172c700fef12..e997a9eb94e1d 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_flows/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { NetworkKpiUniqueFlowsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; @@ -89,7 +89,7 @@ export const useNetworkKpiUniqueFlows = ({ ) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setNetworkKpiUniqueFlowsResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx index d214a8d30bd16..a61d4a859082e 100644 --- a/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx +++ b/x-pack/plugins/security_solution/public/explore/network/containers/kpi_network/unique_private_ips/index.tsx @@ -10,7 +10,7 @@ import { noop } from 'lodash/fp'; import { useCallback, useEffect, useRef, useState } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { NetworkKpiUniquePrivateIpsRequestOptionsInput } from '../../../../../../common/api/search_strategy'; import { useAppToasts } from '../../../../../common/hooks/use_app_toasts'; import type { inputsModel } from '../../../../../common/store'; @@ -99,7 +99,7 @@ export const useNetworkKpiUniquePrivateIps = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setNetworkKpiUniquePrivateIpsResponse((prevResponse) => ({ ...prevResponse, diff --git a/x-pack/plugins/security_solution/public/flyout/left/services/find_alerts.ts b/x-pack/plugins/security_solution/public/flyout/left/services/find_alerts.ts index bee4e8bbe6a20..be33f5ac38aba 100644 --- a/x-pack/plugins/security_solution/public/flyout/left/services/find_alerts.ts +++ b/x-pack/plugins/security_solution/public/flyout/left/services/find_alerts.ts @@ -6,7 +6,7 @@ */ import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { isCompleteResponse, type ISearchStart, isErrorResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse, type ISearchStart } from '@kbn/data-plugin/public'; export interface AlertsQueryParams { alertIds: string[]; @@ -47,14 +47,17 @@ export const createFindAlerts = }, { abortSignal: signal } ) - .subscribe((response) => { - if (isCompleteResponse(response)) { - $subscription.unsubscribe(); - resolve(response.rawResponse); - } else if (isErrorResponse(response)) { + .subscribe({ + next: (response) => { + if (!isRunningResponse(response)) { + $subscription.unsubscribe(); + resolve(response.rawResponse); + } + }, + error: (err) => { $subscription.unsubscribe(); reject(new Error(`Error while loading alerts`)); - } + }, }); }); }; diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts index 086ad78ac3c5f..5f27cbf9cdaed 100644 --- a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts +++ b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/use_ti_data_sources.ts @@ -9,7 +9,7 @@ import { filter } from 'rxjs/operators'; import { useEffect, useState } from 'react'; import { useObservable, withOptionalSignal } from '@kbn/securitysolution-hook-utils'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { isCompleteResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse } from '@kbn/data-plugin/public'; import type { ThreatIntelSourceRequestOptionsInput } from '../../../../common/api/search_strategy'; import { useKibana } from '../../../common/lib/kibana'; import type { @@ -51,7 +51,7 @@ export const getTiDataSourcesComplete = ( ): Observable => { return getTiDataSources(props).pipe( filter((response) => { - return isCompleteResponse(response); + return !isRunningResponse(response); }) ); }; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx index b35c2c86b9abe..5230aa6f561a5 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/details/index.tsx @@ -11,7 +11,7 @@ import ReactDOM from 'react-dom'; import deepEqual from 'fast-deep-equal'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { TimelineEventsDetailsRequestOptionsInput } from '@kbn/timelines-plugin/common'; import { EntityType } from '@kbn/timelines-plugin/common'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; @@ -88,7 +88,7 @@ export const useTimelineEventsDetails = ({ ) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { Promise.resolve().then(() => { ReactDOM.unstable_batchedUpdates(() => { setLoading(false); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index 8d6e871f8354b..077e6448a7812 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -12,7 +12,7 @@ import { useDispatch } from 'react-redux'; import { Subscription } from 'rxjs'; import type { DataView } from '@kbn/data-plugin/common'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { TimelineEqlRequestOptionsInput, TimelineEventsAllOptionsInput, @@ -245,7 +245,7 @@ export const useTimelineEventsHandler = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { endTracking('success'); setLoading(false); setTimelineResponse((prevResponse) => { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx index a260a3d9f9cdd..e217f5e121084 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/kpis/index.tsx @@ -10,7 +10,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import deepEqual from 'fast-deep-equal'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/public'; +import { isRunningResponse } from '@kbn/data-plugin/public'; import { TimelineEventsQueries } from '@kbn/timelines-plugin/common'; import type { inputsModel } from '../../../common/store'; import { useKibana } from '../../../common/lib/kibana'; @@ -63,7 +63,7 @@ export const useTimelineKpis = ({ }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { setLoading(false); setTimelineKpiResponse(response); searchSubscription$.current.unsubscribe(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts index 41f3405bbd7cc..010dd3f0fdfa5 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/elasticsearch/api.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { - IKibanaSearchResponse, - isCompleteResponse, - isErrorResponse, -} from '@kbn/data-plugin/common'; +import { IKibanaSearchResponse, isRunningResponse } from '@kbn/data-plugin/common'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESSearchResponse } from '@kbn/es-types'; import { FETCH_STATUS } from '@kbn/observability-shared-plugin/public'; @@ -40,7 +36,7 @@ export const executeEsQueryAPI = async ({ ) .subscribe({ next: (result) => { - if (isCompleteResponse(result)) { + if (!isRunningResponse(result)) { if (addInspectorRequest) { addInspectorRequest({ data: { @@ -70,33 +66,31 @@ export const executeEsQueryAPI = async ({ } }, error: (err) => { - if (isErrorResponse(err)) { - // eslint-disable-next-line no-console - console.error(err); - reject(err); - if (addInspectorRequest) { - addInspectorRequest({ - data: { - _inspect: [ - getInspectResponse({ - startTime, - esRequestParams: params, - esResponse: null, - esError: { originalError: err, name: err.name, message: err.message }, - esRequestStatus: 2, - operationName: name, - kibanaRequest: { - route: { - path: '/internal/bsearch', - method: 'POST', - }, - } as any, - }), - ], - }, - status: FETCH_STATUS.SUCCESS, - }); - } + // eslint-disable-next-line no-console + console.error(err); + reject(err); + if (addInspectorRequest) { + addInspectorRequest({ + data: { + _inspect: [ + getInspectResponse({ + startTime, + esRequestParams: params, + esResponse: null, + esError: { originalError: err, name: err.name, message: err.message }, + esRequestStatus: 2, + operationName: name, + kibanaRequest: { + route: { + path: '/internal/bsearch', + method: 'POST', + }, + } as any, + }), + ], + }, + status: FETCH_STATUS.SUCCESS, + }); } }, }); diff --git a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx index d99d7c0fc4b01..d9b7c22f83354 100644 --- a/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx +++ b/x-pack/plugins/threat_intelligence/public/modules/indicators/hooks/use_total_count.tsx @@ -9,7 +9,7 @@ import { useEffect, useState } from 'react'; import { IEsSearchRequest, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, } from '@kbn/data-plugin/common'; import { useKibana } from '../../../hooks/use_kibana'; import { useSourcererDataView } from './use_sourcerer_data_view'; @@ -61,7 +61,7 @@ export const useIndicatorsTotalCount = () => { .search>(req) .subscribe({ next: (res) => { - if (isCompleteResponse(res)) { + if (!isRunningResponse(res)) { const returnedCount = res.rawResponse.hits.total || 0; setCount(returnedCount); diff --git a/x-pack/plugins/threat_intelligence/public/utils/search.ts b/x-pack/plugins/threat_intelligence/public/utils/search.ts index 1dac39f74b230..aa0fa68f9038c 100644 --- a/x-pack/plugins/threat_intelligence/public/utils/search.ts +++ b/x-pack/plugins/threat_intelligence/public/utils/search.ts @@ -8,7 +8,7 @@ import { IEsSearchRequest, IKibanaSearchResponse, - isCompleteResponse, + isRunningResponse, } from '@kbn/data-plugin/common'; import { ISearchStart } from '@kbn/data-plugin/public'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; @@ -93,7 +93,7 @@ export const search = async ( }) .subscribe({ next: (response) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { inspect.recordRequestCompletion(searchRequest, response); resolve(response.rawResponse); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx index ef515cf8ffdca..fdc7282f6c817 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.test.tsx @@ -287,9 +287,7 @@ describe('useFetchAlerts', () => { }); it('handles search error', () => { - const obs$ = throwError( - 'simulated search response error, which could be 1) undefined response, 2) response without rawResponse, or 3) partial response' - ); + const obs$ = throwError('simulated search error'); dataSearchMock.mockReturnValue(obs$); const { result } = renderHook(() => useFetchAlerts(args)); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx index 374e2883cc089..acf00da71b5f7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_fetch_alerts.tsx @@ -12,7 +12,7 @@ import { noop } from 'lodash'; import { useCallback, useEffect, useReducer, useRef, useMemo } from 'react'; import { Subscription } from 'rxjs'; -import { isCompleteResponse } from '@kbn/data-plugin/common'; +import { isRunningResponse } from '@kbn/data-plugin/common'; import type { RuleRegistrySearchRequest, RuleRegistrySearchRequestPagination, @@ -206,7 +206,7 @@ const useFetchAlerts = ({ ) .subscribe({ next: (response: RuleRegistrySearchResponse) => { - if (isCompleteResponse(response)) { + if (!isRunningResponse(response)) { const { rawResponse } = response; inspectQuery.current = { request: response?.inspect?.dsl ?? [], diff --git a/x-pack/plugins/ux/public/components/app/rum_dashboard/ux_overview_fetchers.ts b/x-pack/plugins/ux/public/components/app/rum_dashboard/ux_overview_fetchers.ts index 7e7cdbcf0abad..4df3c8c1e8470 100644 --- a/x-pack/plugins/ux/public/components/app/rum_dashboard/ux_overview_fetchers.ts +++ b/x-pack/plugins/ux/public/components/app/rum_dashboard/ux_overview_fetchers.ts @@ -8,7 +8,7 @@ import type { ESSearchResponse } from '@kbn/es-types'; import { DataPublicPluginStart, - isCompleteResponse, + isRunningResponse, } from '@kbn/data-plugin/public'; import { IKibanaSearchRequest } from '@kbn/data-plugin/common'; import { @@ -117,7 +117,7 @@ async function esQuery( }) .subscribe({ next: (result) => { - if (isCompleteResponse(result)) { + if (!isRunningResponse(result)) { resolve(result.rawResponse as any); search$.unsubscribe(); }