Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[search source] remove is_partial check #164506

Merged
merged 46 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
c8b1654
replace isPartialResponse with isRunningResponse
nreese Aug 22, 2023
c32a659
replace isCompleteResponse with isRunningResponse in src/plugins
nreese Aug 22, 2023
cf73a0b
replace isCompleteResponse with isRunningResponse in examples directory
nreese Aug 22, 2023
66c52c1
replace isCompleteResponse with isRunningResponse in x-pack/plugins d…
nreese Aug 22, 2023
2126bcd
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Aug 22, 2023
8625e38
tslint
nreese Aug 22, 2023
d9e3c80
do not throw Received partial response
nreese Aug 22, 2023
36c75b4
Merge branch 'main' into issue_163381
kibanamachine Aug 23, 2023
e0f05a9
fix poll_search test
nreese Aug 23, 2023
066c32c
remove broken test case
nreese Aug 23, 2023
7b8262a
Merge branch 'main' into issue_163381
kibanamachine Aug 25, 2023
95796c4
merge with main
nreese Aug 28, 2023
e4bdfba
fix merge conflict
nreese Aug 28, 2023
efbb44b
fix another merge conflict mistake
nreese Aug 28, 2023
f5af0a2
remove unneeded uses of isErrorResponse
nreese Aug 28, 2023
4667979
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Aug 28, 2023
8c00a67
tslint
nreese Aug 28, 2023
7f6095f
add missing import
nreese Aug 28, 2023
689f4f5
rename isErrorResponse to isMalformedResponse
nreese Aug 28, 2023
5859f4b
update test comments to reflect that execption is no longer thrown fo…
nreese Aug 28, 2023
608b010
clean up useMemo dependencies
nreese Aug 28, 2023
c5b2378
tslint
nreese Aug 28, 2023
17a2a1c
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Aug 28, 2023
af9f687
Merge branch 'main' into issue_163381
kibanamachine Sep 14, 2023
7d03fc7
fix jest tests
nreese Sep 14, 2023
b42e21e
Merge branch 'main' into issue_163381
kibanamachine Sep 14, 2023
9a8a699
fix broken security tests
nreese Sep 14, 2023
75ee676
merge with main
nreese Sep 22, 2023
cdc1a90
rename isMalformedResponse to isAbortedResponse
nreese Sep 22, 2023
d0f5ea5
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Sep 22, 2023
a5fee36
fix jest tests, and remove more usages of is_partial
nreese Sep 22, 2023
f4651ba
rename
nreese Sep 22, 2023
34b8404
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Sep 22, 2023
c416629
remove obsolute test case
nreese Sep 22, 2023
6416ff6
Merge branch 'main' into issue_163381
kibanamachine Sep 25, 2023
c6a729f
Merge branch 'main' into issue_163381
kibanamachine Sep 25, 2023
48bc1a1
Merge branch 'main' into issue_163381
logeekal Sep 26, 2023
bf428ec
Merge branch 'main' into issue_163381
kibanamachine Sep 26, 2023
a5c7ea0
Merge branch 'main' into issue_163381
kibanamachine Sep 27, 2023
66296c8
merge with main
nreese Sep 29, 2023
0214eb2
restore search_response_cache test
nreese Sep 29, 2023
9f3f920
restore search_interceptor test
nreese Sep 29, 2023
0102f27
tslint
nreese Sep 29, 2023
3b3ab03
Merge branch 'main' into issue_163381
kibanamachine Oct 2, 2023
425c6ad
Merge branch 'main' into issue_163381
kibanamachine Oct 2, 2023
c000d44
Merge branch 'main' into issue_163381
patrykkopycinski Oct 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/search_examples/public/search/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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',
Expand Down
4 changes: 2 additions & 2 deletions examples/search_examples/public/search_sessions/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
DataPublicPluginStart,
IEsSearchRequest,
IEsSearchResponse,
isCompleteResponse,
isRunningResponse,
QueryState,
SearchSessionState,
} from '@kbn/data-plugin/public';
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions examples/search_examples/public/sql_search/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { CoreStart } from '@kbn/core/public';
import {
DataPublicPluginStart,
IKibanaSearchResponse,
isCompleteResponse,
isRunningResponse,
} from '@kbn/data-plugin/public';
import {
SQL_SEARCH_STRATEGY,
Expand Down Expand Up @@ -66,7 +66,7 @@ export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDe
})
.subscribe({
next: (res) => {
if (isCompleteResponse(res)) {
if (!isRunningResponse(res)) {
setIsLoading(false);
setResponse(res);
}
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
13 changes: 2 additions & 11 deletions src/plugins/data/common/search/poll_search.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand All @@ -19,7 +19,7 @@ describe('pollSearch', () => {
if (lastCall) {
resolve({
isRunning: false,
isPartial: finishWithError,
isPartial: false,
rawResponse: {},
});
} else {
Expand Down Expand Up @@ -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();
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/data/common/search/poll_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <Response extends IKibanaSearchResponse>(
search: () => Promise<Response>,
Expand Down Expand Up @@ -57,11 +57,11 @@ export const pollSearch = <Response extends IKibanaSearchResponse>(
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<Response>(isPartialResponse, true),
takeWhile<Response>(isRunningResponse, true),
takeUntil<Response>(aborted$)
);
});
Expand Down
12 changes: 3 additions & 9 deletions src/plugins/data/common/search/search_source/search_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<IKibanaSearchResponse<unknown>>((obs) => {
if (isPartialResponse(response)) {
if (isRunningResponse(response)) {
obs.next(this.postFlightTransform(response));
} else {
if (!this.hasPostFlightRequests()) {
Expand Down Expand Up @@ -582,7 +576,7 @@ export class SearchSource {
});
}),
map((response) => {
if (!isCompleteResponse(response)) {
if (isRunningResponse(response)) {
return response;
}
return onResponse(searchRequest, response, options);
Expand Down
198 changes: 15 additions & 183 deletions src/plugins/data/common/search/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
'[email protected]/org.elasticsearch.search.lookup.LeafDocLookup.getFactoryForDoc(LeafDocLookup.java:148)',
'[email protected]/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:191)',
'[email protected]/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: [
'[email protected]/org.elasticsearch.search.lookup.LeafDocLookup.getFactoryForDoc(LeafDocLookup.java:148)',
'[email protected]/org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:191)',
'[email protected]/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);
});
});
});
Loading