This reverts commit 5708c5d004
.
This commit is contained in:
parent
9fcf1f0664
commit
d7cdcf61c7
|
@ -7,7 +7,7 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { bfetch, expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
|
||||
setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
@ -15,7 +15,7 @@ setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { bfetch, e
|
|||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| core | <code>CoreSetup<DataStartDependencies, DataPublicPluginStart></code> | |
|
||||
| { bfetch, expressions, uiActions, usageCollection } | <code>DataSetupDependencies</code> | |
|
||||
| { expressions, uiActions, usageCollection } | <code>DataSetupDependencies</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [bfetch](./kibana-plugin-plugins-data-public.searchinterceptordeps.bfetch.md)
|
||||
|
||||
## SearchInterceptorDeps.bfetch property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
bfetch: BfetchPublicSetup;
|
||||
```
|
|
@ -14,7 +14,6 @@ export interface SearchInterceptorDeps
|
|||
|
||||
| Property | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| [bfetch](./kibana-plugin-plugins-data-public.searchinterceptordeps.bfetch.md) | <code>BfetchPublicSetup</code> | |
|
||||
| [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | <code>CoreSetup['http']</code> | |
|
||||
| [session](./kibana-plugin-plugins-data-public.searchinterceptordeps.session.md) | <code>ISessionService</code> | |
|
||||
| [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | <code>Promise<[CoreStart, any, unknown]></code> | |
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
setup(core: CoreSetup<DataPluginStartDependencies, DataPluginStart>, { bfetch, expressions, usageCollection }: DataPluginSetupDependencies): {
|
||||
setup(core: CoreSetup<DataPluginStartDependencies, DataPluginStart>, { expressions, usageCollection }: DataPluginSetupDependencies): {
|
||||
__enhance: (enhancements: DataEnhancements) => void;
|
||||
search: ISearchSetup;
|
||||
fieldFormats: {
|
||||
|
@ -21,7 +21,7 @@ setup(core: CoreSetup<DataPluginStartDependencies, DataPluginStart>, { bfetch, e
|
|||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| core | <code>CoreSetup<DataPluginStartDependencies, DataPluginStart></code> | |
|
||||
| { bfetch, expressions, usageCollection } | <code>DataPluginSetupDependencies</code> | |
|
||||
| { expressions, usageCollection } | <code>DataPluginSetupDependencies</code> | |
|
||||
|
||||
<b>Returns:</b>
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import { createStreamingBatchedFunction } from './create_streaming_batched_function';
|
||||
import { fetchStreaming as fetchStreamingReal } from '../streaming/fetch_streaming';
|
||||
import { AbortError, defer, of } from '../../../kibana_utils/public';
|
||||
import { defer, of } from '../../../kibana_utils/public';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
const getPromiseState = (promise: Promise<unknown>): Promise<'resolved' | 'rejected' | 'pending'> =>
|
||||
|
@ -168,28 +168,6 @@ describe('createStreamingBatchedFunction()', () => {
|
|||
expect(fetchStreaming).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('ignores a request with an aborted signal', async () => {
|
||||
const { fetchStreaming } = setup();
|
||||
const fn = createStreamingBatchedFunction({
|
||||
url: '/test',
|
||||
fetchStreaming,
|
||||
maxItemAge: 5,
|
||||
flushOnMaxItems: 3,
|
||||
});
|
||||
|
||||
const abortController = new AbortController();
|
||||
abortController.abort();
|
||||
|
||||
of(fn({ foo: 'bar' }, abortController.signal));
|
||||
fn({ baz: 'quix' });
|
||||
|
||||
await new Promise((r) => setTimeout(r, 6));
|
||||
const { body } = fetchStreaming.mock.calls[0][0];
|
||||
expect(JSON.parse(body)).toEqual({
|
||||
batch: [{ baz: 'quix' }],
|
||||
});
|
||||
});
|
||||
|
||||
test('sends POST request to correct endpoint with items in array batched sorted in call order', async () => {
|
||||
const { fetchStreaming } = setup();
|
||||
const fn = createStreamingBatchedFunction({
|
||||
|
@ -445,73 +423,6 @@ describe('createStreamingBatchedFunction()', () => {
|
|||
expect(result3).toEqual({ b: '3' });
|
||||
});
|
||||
|
||||
describe('when requests are aborted', () => {
|
||||
test('aborts stream when all are aborted', async () => {
|
||||
const { fetchStreaming } = setup();
|
||||
const fn = createStreamingBatchedFunction({
|
||||
url: '/test',
|
||||
fetchStreaming,
|
||||
maxItemAge: 5,
|
||||
flushOnMaxItems: 3,
|
||||
});
|
||||
|
||||
const abortController = new AbortController();
|
||||
const promise = fn({ a: '1' }, abortController.signal);
|
||||
const promise2 = fn({ a: '2' }, abortController.signal);
|
||||
await new Promise((r) => setTimeout(r, 6));
|
||||
|
||||
expect(await isPending(promise)).toBe(true);
|
||||
expect(await isPending(promise2)).toBe(true);
|
||||
|
||||
abortController.abort();
|
||||
await new Promise((r) => setTimeout(r, 6));
|
||||
|
||||
expect(await isPending(promise)).toBe(false);
|
||||
expect(await isPending(promise2)).toBe(false);
|
||||
const [, error] = await of(promise);
|
||||
const [, error2] = await of(promise2);
|
||||
expect(error).toBeInstanceOf(AbortError);
|
||||
expect(error2).toBeInstanceOf(AbortError);
|
||||
expect(fetchStreaming.mock.calls[0][0].signal.aborted).toBeTruthy();
|
||||
});
|
||||
|
||||
test('rejects promise on abort and lets others continue', async () => {
|
||||
const { fetchStreaming, stream } = setup();
|
||||
const fn = createStreamingBatchedFunction({
|
||||
url: '/test',
|
||||
fetchStreaming,
|
||||
maxItemAge: 5,
|
||||
flushOnMaxItems: 3,
|
||||
});
|
||||
|
||||
const abortController = new AbortController();
|
||||
const promise = fn({ a: '1' }, abortController.signal);
|
||||
const promise2 = fn({ a: '2' });
|
||||
await new Promise((r) => setTimeout(r, 6));
|
||||
|
||||
expect(await isPending(promise)).toBe(true);
|
||||
|
||||
abortController.abort();
|
||||
await new Promise((r) => setTimeout(r, 6));
|
||||
|
||||
expect(await isPending(promise)).toBe(false);
|
||||
const [, error] = await of(promise);
|
||||
expect(error).toBeInstanceOf(AbortError);
|
||||
|
||||
stream.next(
|
||||
JSON.stringify({
|
||||
id: 1,
|
||||
result: { b: '2' },
|
||||
}) + '\n'
|
||||
);
|
||||
|
||||
await new Promise((r) => setTimeout(r, 1));
|
||||
|
||||
const [result2] = await of(promise2);
|
||||
expect(result2).toEqual({ b: '2' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('when stream closes prematurely', () => {
|
||||
test('rejects pending promises with CONNECTION error code', async () => {
|
||||
const { fetchStreaming, stream } = setup();
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { AbortError, abortSignalToPromise, defer } from '../../../kibana_utils/public';
|
||||
import { defer, Defer } from '../../../kibana_utils/public';
|
||||
import {
|
||||
ItemBufferParams,
|
||||
TimedItemBufferParams,
|
||||
|
@ -27,7 +27,13 @@ import {
|
|||
} from '../../common';
|
||||
import { fetchStreaming, split } from '../streaming';
|
||||
import { normalizeError } from '../../common';
|
||||
import { BatchedFunc, BatchItem } from './types';
|
||||
|
||||
export interface BatchItem<Payload, Result> {
|
||||
payload: Payload;
|
||||
future: Defer<Result>;
|
||||
}
|
||||
|
||||
export type BatchedFunc<Payload, Result> = (payload: Payload) => Promise<Result>;
|
||||
|
||||
export interface BatchedFunctionProtocolError extends ErrorLike {
|
||||
code: string;
|
||||
|
@ -76,67 +82,32 @@ export const createStreamingBatchedFunction = <Payload, Result extends object>(
|
|||
flushOnMaxItems = 25,
|
||||
maxItemAge = 10,
|
||||
} = params;
|
||||
const [fn] = createBatchedFunction({
|
||||
onCall: (payload: Payload, signal?: AbortSignal) => {
|
||||
const [fn] = createBatchedFunction<BatchedFunc<Payload, Result>, BatchItem<Payload, Result>>({
|
||||
onCall: (payload: Payload) => {
|
||||
const future = defer<Result>();
|
||||
const entry: BatchItem<Payload, Result> = {
|
||||
payload,
|
||||
future,
|
||||
signal,
|
||||
};
|
||||
return [future.promise, entry];
|
||||
},
|
||||
onBatch: async (items) => {
|
||||
try {
|
||||
// Filter out any items whose signal is already aborted
|
||||
items = items.filter((item) => {
|
||||
if (item.signal?.aborted) item.future.reject(new AbortError());
|
||||
return !item.signal?.aborted;
|
||||
});
|
||||
|
||||
const donePromises: Array<Promise<any>> = items.map((item) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
const { promise: abortPromise, cleanup } = item.signal
|
||||
? abortSignalToPromise(item.signal)
|
||||
: {
|
||||
promise: undefined,
|
||||
cleanup: () => {},
|
||||
};
|
||||
|
||||
const onDone = () => {
|
||||
resolve();
|
||||
cleanup();
|
||||
};
|
||||
if (abortPromise)
|
||||
abortPromise.catch(() => {
|
||||
item.future.reject(new AbortError());
|
||||
onDone();
|
||||
});
|
||||
item.future.promise.then(onDone, onDone);
|
||||
});
|
||||
});
|
||||
|
||||
// abort when all items were either resolved, rejected or aborted
|
||||
const abortController = new AbortController();
|
||||
let isBatchDone = false;
|
||||
Promise.all(donePromises).then(() => {
|
||||
isBatchDone = true;
|
||||
abortController.abort();
|
||||
});
|
||||
const batch = items.map((item) => item.payload);
|
||||
|
||||
let responsesReceived = 0;
|
||||
const batch = items.map(({ payload }) => payload);
|
||||
const { stream } = fetchStreamingInjected({
|
||||
url,
|
||||
body: JSON.stringify({ batch }),
|
||||
method: 'POST',
|
||||
signal: abortController.signal,
|
||||
});
|
||||
stream.pipe(split('\n')).subscribe({
|
||||
next: (json: string) => {
|
||||
const response = JSON.parse(json) as BatchResponseItem<Result, ErrorLike>;
|
||||
if (response.error) {
|
||||
responsesReceived++;
|
||||
items[response.id].future.reject(response.error);
|
||||
} else if (response.result !== undefined) {
|
||||
responsesReceived++;
|
||||
items[response.id].future.resolve(response.result);
|
||||
}
|
||||
},
|
||||
|
@ -146,7 +117,8 @@ export const createStreamingBatchedFunction = <Payload, Result extends object>(
|
|||
for (const { future } of items) future.reject(normalizedError);
|
||||
},
|
||||
complete: () => {
|
||||
if (!isBatchDone) {
|
||||
const streamTerminatedPrematurely = responsesReceived !== items.length;
|
||||
if (streamTerminatedPrematurely) {
|
||||
const error: BatchedFunctionProtocolError = {
|
||||
message: 'Connection terminated prematurely.',
|
||||
code: 'CONNECTION',
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { Defer } from '../../../kibana_utils/public';
|
||||
|
||||
export interface BatchItem<Payload, Result> {
|
||||
payload: Payload;
|
||||
future: Defer<Result>;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export type BatchedFunc<Payload, Result> = (
|
||||
payload: Payload,
|
||||
signal?: AbortSignal
|
||||
) => Promise<Result>;
|
|
@ -23,8 +23,6 @@ import { BfetchPublicPlugin } from './plugin';
|
|||
export { BfetchPublicSetup, BfetchPublicStart, BfetchPublicContract } from './plugin';
|
||||
export { split } from './streaming';
|
||||
|
||||
export { BatchedFunc } from './batching/types';
|
||||
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new BfetchPublicPlugin(initializerContext);
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ import { fetchStreaming as fetchStreamingStatic, FetchStreamingParams } from './
|
|||
import { removeLeadingSlash } from '../common';
|
||||
import {
|
||||
createStreamingBatchedFunction,
|
||||
BatchedFunc,
|
||||
StreamingBatchedFunctionParams,
|
||||
} from './batching/create_streaming_batched_function';
|
||||
import { BatchedFunc } from './batching/types';
|
||||
|
||||
// eslint-disable-next-line
|
||||
export interface BfetchPublicSetupDependencies {}
|
||||
|
|
|
@ -132,33 +132,6 @@ test('completes stream observable when request finishes', async () => {
|
|||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('completes stream observable when aborted', async () => {
|
||||
const env = setup();
|
||||
const abort = new AbortController();
|
||||
const { stream } = fetchStreaming({
|
||||
url: 'http://example.com',
|
||||
signal: abort.signal,
|
||||
});
|
||||
|
||||
const spy = jest.fn();
|
||||
stream.subscribe({
|
||||
complete: spy,
|
||||
});
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(0);
|
||||
|
||||
(env.xhr as any).responseText = 'foo';
|
||||
env.xhr.onprogress!({} as any);
|
||||
|
||||
abort.abort();
|
||||
|
||||
(env.xhr as any).readyState = 4;
|
||||
(env.xhr as any).status = 200;
|
||||
env.xhr.onreadystatechange!({} as any);
|
||||
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('promise throws when request errors', async () => {
|
||||
const env = setup();
|
||||
const { stream } = fetchStreaming({
|
||||
|
|
|
@ -24,7 +24,6 @@ export interface FetchStreamingParams {
|
|||
headers?: Record<string, string>;
|
||||
method?: 'GET' | 'POST';
|
||||
body?: string;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +35,6 @@ export function fetchStreaming({
|
|||
headers = {},
|
||||
method = 'POST',
|
||||
body = '',
|
||||
signal,
|
||||
}: FetchStreamingParams) {
|
||||
const xhr = new window.XMLHttpRequest();
|
||||
|
||||
|
@ -47,7 +45,7 @@ export function fetchStreaming({
|
|||
// Set the HTTP headers
|
||||
Object.entries(headers).forEach(([k, v]) => xhr.setRequestHeader(k, v));
|
||||
|
||||
const stream = fromStreamingXhr(xhr, signal);
|
||||
const stream = fromStreamingXhr(xhr);
|
||||
|
||||
// Send the payload to the server
|
||||
xhr.send(body);
|
||||
|
|
|
@ -21,7 +21,6 @@ import { fromStreamingXhr } from './from_streaming_xhr';
|
|||
|
||||
const createXhr = (): XMLHttpRequest =>
|
||||
(({
|
||||
abort: () => {},
|
||||
onprogress: () => {},
|
||||
onreadystatechange: () => {},
|
||||
readyState: 0,
|
||||
|
@ -101,39 +100,6 @@ test('completes observable when request reaches end state', () => {
|
|||
expect(complete).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('completes observable when aborted', () => {
|
||||
const xhr = createXhr();
|
||||
const abortController = new AbortController();
|
||||
const observable = fromStreamingXhr(xhr, abortController.signal);
|
||||
|
||||
const next = jest.fn();
|
||||
const complete = jest.fn();
|
||||
observable.subscribe({
|
||||
next,
|
||||
complete,
|
||||
});
|
||||
|
||||
(xhr as any).responseText = '1';
|
||||
xhr.onprogress!({} as any);
|
||||
|
||||
(xhr as any).responseText = '2';
|
||||
xhr.onprogress!({} as any);
|
||||
|
||||
expect(complete).toHaveBeenCalledTimes(0);
|
||||
|
||||
(xhr as any).readyState = 2;
|
||||
abortController.abort();
|
||||
|
||||
expect(complete).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Shouldn't trigger additional events
|
||||
(xhr as any).readyState = 4;
|
||||
(xhr as any).status = 200;
|
||||
xhr.onreadystatechange!({} as any);
|
||||
|
||||
expect(complete).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('errors observable if request returns with error', () => {
|
||||
const xhr = createXhr();
|
||||
const observable = fromStreamingXhr(xhr);
|
||||
|
|
|
@ -26,17 +26,13 @@ import { Observable, Subject } from 'rxjs';
|
|||
export const fromStreamingXhr = (
|
||||
xhr: Pick<
|
||||
XMLHttpRequest,
|
||||
'onprogress' | 'onreadystatechange' | 'readyState' | 'status' | 'responseText' | 'abort'
|
||||
>,
|
||||
signal?: AbortSignal
|
||||
'onprogress' | 'onreadystatechange' | 'readyState' | 'status' | 'responseText'
|
||||
>
|
||||
): Observable<string> => {
|
||||
const subject = new Subject<string>();
|
||||
let index = 0;
|
||||
let aborted = false;
|
||||
|
||||
const processBatch = () => {
|
||||
if (aborted) return;
|
||||
|
||||
const { responseText } = xhr;
|
||||
if (index >= responseText.length) return;
|
||||
subject.next(responseText.substr(index));
|
||||
|
@ -45,19 +41,7 @@ export const fromStreamingXhr = (
|
|||
|
||||
xhr.onprogress = processBatch;
|
||||
|
||||
const onBatchAbort = () => {
|
||||
if (xhr.readyState !== 4) {
|
||||
aborted = true;
|
||||
xhr.abort();
|
||||
subject.complete();
|
||||
if (signal) signal.removeEventListener('abort', onBatchAbort);
|
||||
}
|
||||
};
|
||||
|
||||
if (signal) signal.addEventListener('abort', onBatchAbort);
|
||||
|
||||
xhr.onreadystatechange = () => {
|
||||
if (aborted) return;
|
||||
// Older browsers don't support onprogress, so we need
|
||||
// to call this here, too. It's safe to call this multiple
|
||||
// times even for the same progress event.
|
||||
|
@ -65,8 +49,6 @@ export const fromStreamingXhr = (
|
|||
|
||||
// 4 is the magic number that means the request is done
|
||||
if (xhr.readyState === 4) {
|
||||
if (signal) signal.removeEventListener('abort', onBatchAbort);
|
||||
|
||||
// 0 indicates a network failure. 400+ messages are considered server errors
|
||||
if (xhr.status === 0 || xhr.status >= 400) {
|
||||
subject.error(new Error(`Batch request failed with status ${xhr.status}`));
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"bfetch",
|
||||
"expressions",
|
||||
"uiActions"
|
||||
],
|
||||
|
|
|
@ -105,7 +105,7 @@ export class DataPublicPlugin
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<DataStartDependencies, DataPublicPluginStart>,
|
||||
{ bfetch, expressions, uiActions, usageCollection }: DataSetupDependencies
|
||||
{ expressions, uiActions, usageCollection }: DataSetupDependencies
|
||||
): DataPublicPluginSetup {
|
||||
const startServices = createStartServicesGetter(core.getStartServices);
|
||||
|
||||
|
@ -152,7 +152,6 @@ export class DataPublicPlugin
|
|||
);
|
||||
|
||||
const searchService = this.searchService.setup(core, {
|
||||
bfetch,
|
||||
usageCollection,
|
||||
expressions,
|
||||
});
|
||||
|
|
|
@ -12,7 +12,6 @@ import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch/lib/Transpo
|
|||
import { ApplicationStart } from 'kibana/public';
|
||||
import { Assign } from '@kbn/utility-types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import Boom from '@hapi/boom';
|
||||
import { CoreSetup } from 'src/core/public';
|
||||
import { CoreSetup as CoreSetup_2 } from 'kibana/public';
|
||||
|
@ -1727,7 +1726,7 @@ export class Plugin implements Plugin_2<DataPublicPluginSetup, DataPublicPluginS
|
|||
// Warning: (ae-forgotten-export) The symbol "ConfigSchema" needs to be exported by the entry point index.d.ts
|
||||
constructor(initializerContext: PluginInitializerContext_2<ConfigSchema>);
|
||||
// (undocumented)
|
||||
setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { bfetch, expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
|
||||
setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
|
||||
// (undocumented)
|
||||
start(core: CoreStart_2, { uiActions }: DataStartDependencies): DataPublicPluginStart;
|
||||
// (undocumented)
|
||||
|
@ -2102,8 +2101,6 @@ export class SearchInterceptor {
|
|||
//
|
||||
// @public (undocumented)
|
||||
export interface SearchInterceptorDeps {
|
||||
// (undocumented)
|
||||
bfetch: BfetchPublicSetup;
|
||||
// (undocumented)
|
||||
http: CoreSetup_2['http'];
|
||||
// (undocumented)
|
||||
|
|
|
@ -25,13 +25,9 @@ import { AbortError } from '../../../kibana_utils/public';
|
|||
import { SearchTimeoutError, PainlessError, TimeoutErrorMode } from './errors';
|
||||
import { searchServiceMock } from './mocks';
|
||||
import { ISearchStart } from '.';
|
||||
import { bfetchPluginMock } from '../../../bfetch/public/mocks';
|
||||
import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
|
||||
let searchInterceptor: SearchInterceptor;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
let bfetchSetup: jest.Mocked<BfetchPublicSetup>;
|
||||
let fetchMock: jest.Mock<any>;
|
||||
|
||||
const flushPromises = () => new Promise((resolve) => setImmediate(resolve));
|
||||
jest.useFakeTimers();
|
||||
|
@ -43,11 +39,7 @@ describe('SearchInterceptor', () => {
|
|||
mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
searchMock = searchServiceMock.createStartContract();
|
||||
fetchMock = jest.fn();
|
||||
bfetchSetup = bfetchPluginMock.createSetupContract();
|
||||
bfetchSetup.batchedFunction.mockReturnValue(fetchMock);
|
||||
searchInterceptor = new SearchInterceptor({
|
||||
bfetch: bfetchSetup,
|
||||
toasts: mockCoreSetup.notifications.toasts,
|
||||
startServices: new Promise((resolve) => {
|
||||
resolve([mockCoreStart, {}, {}]);
|
||||
|
@ -102,7 +94,7 @@ describe('SearchInterceptor', () => {
|
|||
describe('search', () => {
|
||||
test('Observable should resolve if fetch is successful', async () => {
|
||||
const mockResponse: any = { result: 200 };
|
||||
fetchMock.mockResolvedValueOnce(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockResolvedValueOnce(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -113,7 +105,7 @@ describe('SearchInterceptor', () => {
|
|||
describe('Should throw typed errors', () => {
|
||||
test('Observable should fail if fetch has an internal error', async () => {
|
||||
const mockResponse: any = new Error('Internal Error');
|
||||
fetchMock.mockRejectedValue(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValue(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -129,7 +121,7 @@ describe('SearchInterceptor', () => {
|
|||
message: 'Request timed out',
|
||||
},
|
||||
};
|
||||
fetchMock.mockRejectedValueOnce(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -145,7 +137,7 @@ describe('SearchInterceptor', () => {
|
|||
message: 'Request timed out',
|
||||
},
|
||||
};
|
||||
fetchMock.mockRejectedValue(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValue(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -166,7 +158,7 @@ describe('SearchInterceptor', () => {
|
|||
message: 'Request timed out',
|
||||
},
|
||||
};
|
||||
fetchMock.mockRejectedValue(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValue(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -187,7 +179,7 @@ describe('SearchInterceptor', () => {
|
|||
message: 'Request timed out',
|
||||
},
|
||||
};
|
||||
fetchMock.mockRejectedValue(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValue(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -220,7 +212,7 @@ describe('SearchInterceptor', () => {
|
|||
},
|
||||
},
|
||||
};
|
||||
fetchMock.mockRejectedValueOnce(mockResponse);
|
||||
mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse);
|
||||
const mockRequest: IEsSearchRequest = {
|
||||
params: {},
|
||||
};
|
||||
|
@ -230,7 +222,7 @@ describe('SearchInterceptor', () => {
|
|||
|
||||
test('Observable should fail if user aborts (test merged signal)', async () => {
|
||||
const abortController = new AbortController();
|
||||
fetchMock.mockImplementationOnce((options: any) => {
|
||||
mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
options.signal.addEventListener('abort', () => {
|
||||
reject(new AbortError());
|
||||
|
@ -268,7 +260,7 @@ describe('SearchInterceptor', () => {
|
|||
|
||||
const error = (e: any) => {
|
||||
expect(e).toBeInstanceOf(AbortError);
|
||||
expect(fetchMock).not.toBeCalled();
|
||||
expect(mockCoreSetup.http.fetch).not.toBeCalled();
|
||||
done();
|
||||
};
|
||||
response.subscribe({ error });
|
||||
|
|
|
@ -17,17 +17,17 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { get, memoize } from 'lodash';
|
||||
import { get, memoize, trimEnd } from 'lodash';
|
||||
import { BehaviorSubject, throwError, timer, defer, from, Observable, NEVER } from 'rxjs';
|
||||
import { catchError, finalize } from 'rxjs/operators';
|
||||
import { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { BatchedFunc, BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import {
|
||||
IKibanaSearchRequest,
|
||||
IKibanaSearchResponse,
|
||||
ISearchOptions,
|
||||
ES_SEARCH_STRATEGY,
|
||||
ISessionService,
|
||||
} from '../../common';
|
||||
import { SearchUsageCollector } from './collectors';
|
||||
|
@ -44,7 +44,6 @@ import { toMountPoint } from '../../../kibana_react/public';
|
|||
import { AbortError, getCombinedAbortSignal } from '../../../kibana_utils/public';
|
||||
|
||||
export interface SearchInterceptorDeps {
|
||||
bfetch: BfetchPublicSetup;
|
||||
http: CoreSetup['http'];
|
||||
uiSettings: CoreSetup['uiSettings'];
|
||||
startServices: Promise<[CoreStart, any, unknown]>;
|
||||
|
@ -70,10 +69,6 @@ export class SearchInterceptor {
|
|||
* @internal
|
||||
*/
|
||||
protected application!: CoreStart['application'];
|
||||
private batchedFetch!: BatchedFunc<
|
||||
{ request: IKibanaSearchRequest; options: ISearchOptions },
|
||||
IKibanaSearchResponse
|
||||
>;
|
||||
|
||||
/*
|
||||
* @internal
|
||||
|
@ -84,10 +79,6 @@ export class SearchInterceptor {
|
|||
this.deps.startServices.then(([coreStart]) => {
|
||||
this.application = coreStart.application;
|
||||
});
|
||||
|
||||
this.batchedFetch = deps.bfetch.batchedFunction({
|
||||
url: '/internal/bsearch',
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -137,14 +128,24 @@ export class SearchInterceptor {
|
|||
request: IKibanaSearchRequest,
|
||||
options?: ISearchOptions
|
||||
): Promise<IKibanaSearchResponse> {
|
||||
const { abortSignal, ...requestOptions } = options || {};
|
||||
return this.batchedFetch(
|
||||
{
|
||||
request,
|
||||
options: requestOptions,
|
||||
},
|
||||
abortSignal
|
||||
const { id, ...searchRequest } = request;
|
||||
const path = trimEnd(
|
||||
`/internal/search/${options?.strategy ?? ES_SEARCH_STRATEGY}/${id ?? ''}`,
|
||||
'/'
|
||||
);
|
||||
const body = JSON.stringify({
|
||||
sessionId: options?.sessionId,
|
||||
isStored: options?.isStored,
|
||||
isRestore: options?.isRestore,
|
||||
...searchRequest,
|
||||
});
|
||||
|
||||
return this.deps.http.fetch({
|
||||
method: 'POST',
|
||||
path,
|
||||
body,
|
||||
signal: options?.abortSignal,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,6 @@ import { coreMock } from '../../../../core/public/mocks';
|
|||
import { CoreSetup, CoreStart } from '../../../../core/public';
|
||||
|
||||
import { SearchService, SearchServiceSetupDependencies } from './search_service';
|
||||
import { bfetchPluginMock } from '../../../bfetch/public/mocks';
|
||||
|
||||
describe('Search service', () => {
|
||||
let searchService: SearchService;
|
||||
|
@ -40,10 +39,8 @@ describe('Search service', () => {
|
|||
|
||||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const bfetch = bfetchPluginMock.createSetupContract();
|
||||
const setup = searchService.setup(mockCoreSetup, ({
|
||||
packageInfo: { version: '8' },
|
||||
bfetch,
|
||||
expressions: { registerFunction: jest.fn(), registerType: jest.fn() },
|
||||
} as unknown) as SearchServiceSetupDependencies);
|
||||
expect(setup).toHaveProperty('aggs');
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import { Plugin, CoreSetup, CoreStart, PluginInitializerContext } from 'src/core/public';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import { ISearchSetup, ISearchStart, SearchEnhancements } from './types';
|
||||
|
||||
import { handleResponse } from './fetch';
|
||||
|
@ -50,7 +49,6 @@ import { aggShardDelay } from '../../common/search/aggs/buckets/shard_delay_fn';
|
|||
|
||||
/** @internal */
|
||||
export interface SearchServiceSetupDependencies {
|
||||
bfetch: BfetchPublicSetup;
|
||||
expressions: ExpressionsSetup;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
}
|
||||
|
@ -72,7 +70,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
|
||||
public setup(
|
||||
{ http, getStartServices, notifications, uiSettings }: CoreSetup,
|
||||
{ bfetch, expressions, usageCollection }: SearchServiceSetupDependencies
|
||||
{ expressions, usageCollection }: SearchServiceSetupDependencies
|
||||
): ISearchSetup {
|
||||
this.usageCollector = createUsageCollector(getStartServices, usageCollection);
|
||||
|
||||
|
@ -82,7 +80,6 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
* all pending search requests, as well as getting the number of pending search requests.
|
||||
*/
|
||||
this.searchInterceptor = new SearchInterceptor({
|
||||
bfetch,
|
||||
toasts: notifications.toasts,
|
||||
http,
|
||||
uiSettings,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import React from 'react';
|
||||
import { CoreStart } from 'src/core/public';
|
||||
import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
|
||||
import { ExpressionsSetup } from 'src/plugins/expressions/public';
|
||||
import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public';
|
||||
|
@ -37,7 +36,6 @@ export interface DataPublicPluginEnhancements {
|
|||
}
|
||||
|
||||
export interface DataSetupDependencies {
|
||||
bfetch: BfetchPublicSetup;
|
||||
expressions: ExpressionsSetup;
|
||||
uiActions: UiActionsSetup;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from 'src/core/server';
|
||||
import { ExpressionsServerSetup } from 'src/plugins/expressions/server';
|
||||
import { BfetchServerSetup } from 'src/plugins/bfetch/server';
|
||||
import { ConfigSchema } from '../config';
|
||||
import { IndexPatternsService, IndexPatternsServiceStart } from './index_patterns';
|
||||
import { ISearchSetup, ISearchStart, SearchEnhancements } from './search';
|
||||
|
@ -52,7 +51,6 @@ export interface DataPluginStart {
|
|||
}
|
||||
|
||||
export interface DataPluginSetupDependencies {
|
||||
bfetch: BfetchServerSetup;
|
||||
expressions: ExpressionsServerSetup;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
}
|
||||
|
@ -87,7 +85,7 @@ export class DataServerPlugin
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<DataPluginStartDependencies, DataPluginStart>,
|
||||
{ bfetch, expressions, usageCollection }: DataPluginSetupDependencies
|
||||
{ expressions, usageCollection }: DataPluginSetupDependencies
|
||||
) {
|
||||
this.indexPatterns.setup(core);
|
||||
this.scriptsService.setup(core);
|
||||
|
@ -98,7 +96,6 @@ export class DataServerPlugin
|
|||
core.uiSettings.register(getUiSettings());
|
||||
|
||||
const searchSetup = this.searchService.setup(core, {
|
||||
bfetch,
|
||||
expressions,
|
||||
usageCollection,
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
import { Observable } from 'rxjs';
|
||||
import { first, map } from 'rxjs/operators';
|
||||
import { first } from 'rxjs/operators';
|
||||
|
||||
import type { Logger } from 'kibana/server';
|
||||
import type { ApiResponse } from '@elastic/elasticsearch';
|
||||
|
@ -30,7 +30,6 @@ import { getDefaultSearchParams, getShardTimeout } from '../es_search';
|
|||
import type { ISearchStrategy } from '../types';
|
||||
import type { SearchUsage } from '../collectors/usage';
|
||||
import type { IEsRawSearchResponse } from '../../../common';
|
||||
import { shimHitsTotal } from '..';
|
||||
|
||||
export const esSearchStrategyProvider = (
|
||||
config$: Observable<SharedGlobalConfig>,
|
||||
|
@ -55,10 +54,6 @@ export const esSearchStrategyProvider = (
|
|||
return esClient.asCurrentUser.search(params);
|
||||
}, abortSignal).pipe(
|
||||
toKibanaSearchResponse(),
|
||||
map((response) => ({
|
||||
...response,
|
||||
rawResponse: shimHitsTotal(response.rawResponse),
|
||||
})),
|
||||
trackSearchStatus(logger, usage),
|
||||
includeTotalLoaded()
|
||||
);
|
||||
|
|
|
@ -25,8 +25,6 @@ import { createFieldFormatsStartMock } from '../field_formats/mocks';
|
|||
import { createIndexPatternsStartMock } from '../index_patterns/mocks';
|
||||
|
||||
import { SearchService, SearchServiceSetupDependencies } from './search_service';
|
||||
import { bfetchPluginMock } from '../../../bfetch/server/mocks';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
describe('Search service', () => {
|
||||
let plugin: SearchService;
|
||||
|
@ -37,29 +35,15 @@ describe('Search service', () => {
|
|||
const mockLogger: any = {
|
||||
debug: () => {},
|
||||
};
|
||||
const context = coreMock.createPluginInitializerContext({});
|
||||
context.config.create = jest.fn().mockImplementation(() => {
|
||||
return of({
|
||||
search: {
|
||||
aggs: {
|
||||
shardDelay: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
plugin = new SearchService(context, mockLogger);
|
||||
plugin = new SearchService(coreMock.createPluginInitializerContext({}), mockLogger);
|
||||
mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
});
|
||||
|
||||
describe('setup()', () => {
|
||||
it('exposes proper contract', async () => {
|
||||
const bfetch = bfetchPluginMock.createSetupContract();
|
||||
const setup = plugin.setup(mockCoreSetup, ({
|
||||
packageInfo: { version: '8' },
|
||||
bfetch,
|
||||
expressions: {
|
||||
registerFunction: jest.fn(),
|
||||
registerType: jest.fn(),
|
||||
|
|
|
@ -29,8 +29,7 @@ import {
|
|||
SharedGlobalConfig,
|
||||
StartServicesAccessor,
|
||||
} from 'src/core/server';
|
||||
import { catchError, first, switchMap } from 'rxjs/operators';
|
||||
import { BfetchServerSetup } from 'src/plugins/bfetch/server';
|
||||
import { first, switchMap } from 'rxjs/operators';
|
||||
import { ExpressionsServerSetup } from 'src/plugins/expressions/server';
|
||||
import {
|
||||
ISearchSetup,
|
||||
|
@ -86,7 +85,6 @@ type StrategyMap = Record<string, ISearchStrategy<any, any>>;
|
|||
|
||||
/** @internal */
|
||||
export interface SearchServiceSetupDependencies {
|
||||
bfetch: BfetchServerSetup;
|
||||
expressions: ExpressionsServerSetup;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
}
|
||||
|
@ -108,7 +106,6 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
private readonly searchSourceService = new SearchSourceService();
|
||||
private defaultSearchStrategyName: string = ES_SEARCH_STRATEGY;
|
||||
private searchStrategies: StrategyMap = {};
|
||||
private coreStart?: CoreStart;
|
||||
private sessionService: BackgroundSessionService = new BackgroundSessionService();
|
||||
|
||||
constructor(
|
||||
|
@ -118,7 +115,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<{}, DataPluginStart>,
|
||||
{ bfetch, expressions, usageCollection }: SearchServiceSetupDependencies
|
||||
{ expressions, usageCollection }: SearchServiceSetupDependencies
|
||||
): ISearchSetup {
|
||||
const usage = usageCollection ? usageProvider(core) : undefined;
|
||||
|
||||
|
@ -131,13 +128,10 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
registerMsearchRoute(router, routeDependencies);
|
||||
registerSessionRoutes(router);
|
||||
|
||||
core.getStartServices().then(([coreStart]) => {
|
||||
this.coreStart = coreStart;
|
||||
});
|
||||
|
||||
core.http.registerRouteHandlerContext('search', async (context, request) => {
|
||||
const search = this.asScopedProvider(this.coreStart!)(request);
|
||||
const session = this.sessionService.asScopedProvider(this.coreStart!)(request);
|
||||
const [coreStart] = await core.getStartServices();
|
||||
const search = this.asScopedProvider(coreStart)(request);
|
||||
const session = this.sessionService.asScopedProvider(coreStart)(request);
|
||||
return { ...search, session };
|
||||
});
|
||||
|
||||
|
@ -152,36 +146,6 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
|
|||
)
|
||||
);
|
||||
|
||||
bfetch.addBatchProcessingRoute<{ request: any; options?: ISearchOptions }, any>(
|
||||
'/internal/bsearch',
|
||||
(request) => {
|
||||
const search = this.asScopedProvider(this.coreStart!)(request);
|
||||
|
||||
return {
|
||||
onBatchItem: async ({ request: requestData, options }) => {
|
||||
return search
|
||||
.search(requestData, options)
|
||||
.pipe(
|
||||
first(),
|
||||
catchError((err) => {
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw {
|
||||
statusCode: err.statusCode || 500,
|
||||
body: {
|
||||
message: err.message,
|
||||
attributes: {
|
||||
error: err.body?.error || err.message,
|
||||
},
|
||||
},
|
||||
};
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
core.savedObjects.registerType(searchTelemetry);
|
||||
if (usageCollection) {
|
||||
registerUsageCollector(usageCollection, this.initializerContext);
|
||||
|
|
|
@ -9,7 +9,6 @@ import { Adapters } from 'src/plugins/inspector/common';
|
|||
import { ApiResponse } from '@elastic/elasticsearch';
|
||||
import { Assign } from '@kbn/utility-types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BfetchServerSetup } from 'src/plugins/bfetch/server';
|
||||
import { ConfigDeprecationProvider } from '@kbn/config';
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
import { CoreSetup as CoreSetup_2 } from 'kibana/server';
|
||||
|
@ -955,7 +954,7 @@ export function parseInterval(interval: string): moment.Duration | null;
|
|||
export class Plugin implements Plugin_2<PluginSetup, PluginStart, DataPluginSetupDependencies, DataPluginStartDependencies> {
|
||||
constructor(initializerContext: PluginInitializerContext_2<ConfigSchema>);
|
||||
// (undocumented)
|
||||
setup(core: CoreSetup<DataPluginStartDependencies, PluginStart>, { bfetch, expressions, usageCollection }: DataPluginSetupDependencies): {
|
||||
setup(core: CoreSetup<DataPluginStartDependencies, PluginStart>, { expressions, usageCollection }: DataPluginSetupDependencies): {
|
||||
__enhance: (enhancements: DataEnhancements) => void;
|
||||
search: ISearchSetup;
|
||||
fieldFormats: {
|
||||
|
@ -1253,7 +1252,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
|
|||
// src/plugins/data/server/index.ts:284:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/index.ts:287: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:58:14 - (ae-forgotten-export) The symbol "IndexPatternsService" needs to be exported by the entry point index.d.ts
|
||||
// src/plugins/data/server/plugin.ts:90:74 - (ae-forgotten-export) The symbol "DataEnhancements" 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:104:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
|
|
@ -267,13 +267,14 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
|||
},
|
||||
[UI_SETTINGS.COURIER_BATCH_SEARCHES]: {
|
||||
name: i18n.translate('data.advancedSettings.courier.batchSearchesTitle', {
|
||||
defaultMessage: 'Use legacy search',
|
||||
defaultMessage: 'Batch concurrent searches',
|
||||
}),
|
||||
value: false,
|
||||
type: 'boolean',
|
||||
description: i18n.translate('data.advancedSettings.courier.batchSearchesText', {
|
||||
defaultMessage: `Kibana uses a new search and batching infrastructure.
|
||||
Enable this option if you prefer to fallback to the legacy synchronous behavior`,
|
||||
defaultMessage: `When disabled, dashboard panels will load individually, and search requests will terminate when users navigate
|
||||
away or update the query. When enabled, dashboard panels will load together when all of the data is loaded, and
|
||||
searches will not terminate.`,
|
||||
}),
|
||||
deprecation: {
|
||||
message: i18n.translate('data.advancedSettings.courier.batchSearchesTextDeprecation', {
|
||||
|
|
|
@ -12,7 +12,6 @@ import { ApiResponse as ApiResponse_2 } from '@elastic/elasticsearch';
|
|||
import { ApplicationStart as ApplicationStart_2 } from 'kibana/public';
|
||||
import { Assign } from '@kbn/utility-types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import Boom from '@hapi/boom';
|
||||
import { CoreSetup as CoreSetup_2 } from 'src/core/public';
|
||||
import { CoreSetup as CoreSetup_3 } from 'kibana/public';
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
"xpack", "data_enhanced"
|
||||
],
|
||||
"requiredPlugins": [
|
||||
"bfetch",
|
||||
"data",
|
||||
"features"
|
||||
],
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import React from 'react';
|
||||
import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'src/core/public';
|
||||
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public';
|
||||
import { BfetchPublicSetup } from '../../../../src/plugins/bfetch/public';
|
||||
|
||||
import { setAutocompleteService } from './services';
|
||||
import { setupKqlQuerySuggestionProvider, KUERY_LANGUAGE_NAME } from './autocomplete';
|
||||
|
@ -17,7 +16,6 @@ import { createConnectedBackgroundSessionIndicator } from './search';
|
|||
import { ConfigSchema } from '../config';
|
||||
|
||||
export interface DataEnhancedSetupDependencies {
|
||||
bfetch: BfetchPublicSetup;
|
||||
data: DataPublicPluginSetup;
|
||||
}
|
||||
export interface DataEnhancedStartDependencies {
|
||||
|
@ -35,7 +33,7 @@ export class DataEnhancedPlugin
|
|||
|
||||
public setup(
|
||||
core: CoreSetup<DataEnhancedStartDependencies>,
|
||||
{ bfetch, data }: DataEnhancedSetupDependencies
|
||||
{ data }: DataEnhancedSetupDependencies
|
||||
) {
|
||||
data.autocomplete.addQuerySuggestionProvider(
|
||||
KUERY_LANGUAGE_NAME,
|
||||
|
@ -43,7 +41,6 @@ export class DataEnhancedPlugin
|
|||
);
|
||||
|
||||
this.enhancedSearchInterceptor = new EnhancedSearchInterceptor({
|
||||
bfetch,
|
||||
toasts: core.notifications.toasts,
|
||||
http: core.http,
|
||||
uiSettings: core.uiSettings,
|
||||
|
|
|
@ -11,7 +11,6 @@ import { UI_SETTINGS } from '../../../../../src/plugins/data/common';
|
|||
import { AbortError } from '../../../../../src/plugins/kibana_utils/public';
|
||||
import { SearchTimeoutError } from 'src/plugins/data/public';
|
||||
import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks';
|
||||
import { bfetchPluginMock } from '../../../../../src/plugins/bfetch/public/mocks';
|
||||
|
||||
const timeTravel = (msToRun = 0) => {
|
||||
jest.advanceTimersByTime(msToRun);
|
||||
|
@ -25,13 +24,12 @@ const complete = jest.fn();
|
|||
let searchInterceptor: EnhancedSearchInterceptor;
|
||||
let mockCoreSetup: MockedKeys<CoreSetup>;
|
||||
let mockCoreStart: MockedKeys<CoreStart>;
|
||||
let fetchMock: jest.Mock<any>;
|
||||
|
||||
jest.useFakeTimers();
|
||||
|
||||
function mockFetchImplementation(responses: any[]) {
|
||||
let i = 0;
|
||||
fetchMock.mockImplementation(() => {
|
||||
mockCoreSetup.http.fetch.mockImplementation(() => {
|
||||
const { time = 0, value = {}, isError = false } = responses[i++];
|
||||
return new Promise((resolve, reject) =>
|
||||
setTimeout(() => {
|
||||
|
@ -48,7 +46,6 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
mockCoreSetup = coreMock.createSetup();
|
||||
mockCoreStart = coreMock.createStart();
|
||||
const dataPluginMockStart = dataPluginMock.createStartContract();
|
||||
fetchMock = jest.fn();
|
||||
|
||||
mockCoreSetup.uiSettings.get.mockImplementation((name: string) => {
|
||||
switch (name) {
|
||||
|
@ -77,11 +74,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
const bfetchMock = bfetchPluginMock.createSetupContract();
|
||||
bfetchMock.batchedFunction.mockReturnValue(fetchMock);
|
||||
|
||||
searchInterceptor = new EnhancedSearchInterceptor({
|
||||
bfetch: bfetchMock,
|
||||
toasts: mockCoreSetup.notifications.toasts,
|
||||
startServices: mockPromise as any,
|
||||
http: mockCoreSetup.http,
|
||||
|
@ -254,7 +247,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
expect(error).toHaveBeenCalled();
|
||||
expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError);
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.delete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -278,7 +271,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
expect(error).toHaveBeenCalled();
|
||||
expect(error.mock.calls[0][0]).toBeInstanceOf(SearchTimeoutError);
|
||||
expect(fetchMock).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.delete).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -310,7 +303,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
expect(next).toHaveBeenCalled();
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
expect(fetchMock).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.delete).not.toHaveBeenCalled();
|
||||
|
||||
// Long enough to reach the timeout but not long enough to reach the next response
|
||||
|
@ -318,7 +311,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
expect(error).toHaveBeenCalled();
|
||||
expect(error.mock.calls[0][0]).toBeInstanceOf(SearchTimeoutError);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.delete).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -352,7 +345,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
expect(next).toHaveBeenCalled();
|
||||
expect(error).not.toHaveBeenCalled();
|
||||
expect(fetchMock).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalled();
|
||||
expect(mockCoreSetup.http.delete).not.toHaveBeenCalled();
|
||||
|
||||
// Long enough to reach the timeout but not long enough to reach the next response
|
||||
|
@ -360,7 +353,7 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
expect(error).toHaveBeenCalled();
|
||||
expect(error.mock.calls[0][0]).toBe(responses[1].value);
|
||||
expect(fetchMock).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2);
|
||||
expect(mockCoreSetup.http.delete).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
@ -392,7 +385,9 @@ describe('EnhancedSearchInterceptor', () => {
|
|||
|
||||
await timeTravel();
|
||||
|
||||
const areAllRequestsAborted = fetchMock.mock.calls.every(([_, signal]) => signal?.aborted);
|
||||
const areAllRequestsAborted = mockCoreSetup.http.fetch.mock.calls.every(
|
||||
([{ signal }]) => signal?.aborted
|
||||
);
|
||||
expect(areAllRequestsAborted).toBe(true);
|
||||
expect(mockUsageCollector.trackQueriesCancelled).toBeCalledTimes(1);
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue