From 2186162dfaca5850beb43f386abeb4dc8c440742 Mon Sep 17 00:00:00 2001 From: Liza Katz Date: Thu, 13 Aug 2020 11:28:39 +0300 Subject: [PATCH] Data plugin: Suggested enhance pattern (#74505) * improve test stability * Enhance pattern * fix tests * fix test * Rename enhance to __enhance * Deleted unnecessary attribute * ISearchInterceptor interface * docs * Clean up internal docs * jest Co-authored-by: Elastic Machine --- ...ublic.searchinterceptor.abortcontroller.md | 13 ----- ...blic.searchinterceptor.getpendingcount_.md | 8 ++- ...data-public.searchinterceptor.hidetoast.md | 11 ---- ...blic.searchinterceptor.longrunningtoast.md | 13 ----- ...n-plugins-data-public.searchinterceptor.md | 11 +--- ...a-public.searchinterceptor.pendingcount.md | 13 ----- ...-public.searchinterceptor.pendingcount_.md | 13 ----- ...ns-data-public.searchinterceptor.search.md | 2 +- ...data-public.searchinterceptor.showtoast.md | 11 ---- ....searchinterceptor.timeoutsubscriptions.md | 13 ----- ...-data-public.searchinterceptordeps.http.md | 2 +- ...ugins-data-public.searchinterceptordeps.md | 8 +-- ...ic.searchinterceptordeps.startservices.md} | 6 +-- ...ata-public.searchinterceptordeps.toasts.md | 2 +- ...public.searchinterceptordeps.uisettings.md | 2 +- src/plugins/data/public/mocks.ts | 1 + src/plugins/data/public/plugin.ts | 18 ++++--- src/plugins/data/public/public.api.md | 35 ++++++++----- src/plugins/data/public/search/index.ts | 9 +++- src/plugins/data/public/search/mocks.ts | 2 +- .../public/search/search_interceptor.test.ts | 28 +++++------ .../data/public/search/search_interceptor.ts | 50 ++++++++++++------- .../data/public/search/search_service.test.ts | 2 +- .../data/public/search/search_service.ts | 35 +++++++------ src/plugins/data/public/search/types.ts | 16 ++++-- src/plugins/data/public/types.ts | 10 +++- x-pack/plugins/data_enhanced/public/plugin.ts | 18 ++++--- .../public/search/search_interceptor.test.ts | 48 +++++++++++------- .../public/search/search_interceptor.ts | 7 ++- 29 files changed, 194 insertions(+), 213 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md rename docs/development/plugins/data/public/{kibana-plugin-plugins-data-public.searchinterceptordeps.application.md => kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md} (61%) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md deleted file mode 100644 index 0451a2254dc40..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [abortController](./kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md) - -## SearchInterceptor.abortController property - -`abortController` used to signal all searches to abort. - -Signature: - -```typescript -protected abortController: AbortController; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md index db2c5d6957ad7..ef36b3f37b0c7 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md @@ -2,12 +2,16 @@ [Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [getPendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) -## SearchInterceptor.getPendingCount$ property +## SearchInterceptor.getPendingCount$() method Returns an `Observable` over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. Signature: ```typescript -getPendingCount$: () => Observable; +getPendingCount$(): Observable; ``` +Returns: + +`Observable` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md deleted file mode 100644 index 59938a755a99e..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [hideToast](./kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md) - -## SearchInterceptor.hideToast property - -Signature: - -```typescript -protected hideToast: () => void; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md deleted file mode 100644 index 5799039de91bc..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [longRunningToast](./kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md) - -## SearchInterceptor.longRunningToast property - -The current long-running toast (if there is one). - -Signature: - -```typescript -protected longRunningToast?: Toast; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index b3b7da05326d0..32954927504ae 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -20,22 +20,15 @@ export declare class SearchInterceptor | Property | Modifiers | Type | Description | | --- | --- | --- | --- | -| [abortController](./kibana-plugin-plugins-data-public.searchinterceptor.abortcontroller.md) | | AbortController | abortController used to signal all searches to abort. | | [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps | | -| [getPendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | () => Observable<number> | Returns an Observable over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. | -| [hideToast](./kibana-plugin-plugins-data-public.searchinterceptor.hidetoast.md) | | () => void | | -| [longRunningToast](./kibana-plugin-plugins-data-public.searchinterceptor.longrunningtoast.md) | | Toast | The current long-running toast (if there is one). | -| [pendingCount](./kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md) | | number | The number of pending search requests. | -| [pendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md) | | BehaviorSubject<number> | Observable that emits when the number of pending requests changes. | | [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) | | number | undefined | | -| [showToast](./kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md) | | () => void | | -| [timeoutSubscriptions](./kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md) | | Subscription | The subscriptions from scheduling the automatic timeout for each request. | ## Methods | Method | Modifiers | Description | | --- | --- | --- | +| [getPendingCount$()](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | Returns an Observable over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. | | [runSearch(request, signal, strategy)](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) | | | -| [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates the pendingCount when the request is started/finalized. | +| [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates pendingCount$ when the request is started/finalized. | | [setupTimers(options)](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md deleted file mode 100644 index 7dd2bd3e6703f..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [pendingCount](./kibana-plugin-plugins-data-public.searchinterceptor.pendingcount.md) - -## SearchInterceptor.pendingCount property - -The number of pending search requests. - -Signature: - -```typescript -protected pendingCount: number; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md deleted file mode 100644 index dad0fca0bfe08..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [pendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.pendingcount_.md) - -## SearchInterceptor.pendingCount$ property - -Observable that emits when the number of pending requests changes. - -Signature: - -```typescript -protected pendingCount$: BehaviorSubject; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md index 38ddda7b4e184..1752d183a8737 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.search.md @@ -4,7 +4,7 @@ ## SearchInterceptor.search() method -Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort either when `cancelPending` is called, when the request times out, or when the original `AbortSignal` is aborted. Updates the `pendingCount` when the request is started/finalized. +Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort either when `cancelPending` is called, when the request times out, or when the original `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized. Signature: diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md deleted file mode 100644 index e495c72b57215..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [showToast](./kibana-plugin-plugins-data-public.searchinterceptor.showtoast.md) - -## SearchInterceptor.showToast property - -Signature: - -```typescript -protected showToast: () => void; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md deleted file mode 100644 index 12f200e037784..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md +++ /dev/null @@ -1,13 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [timeoutSubscriptions](./kibana-plugin-plugins-data-public.searchinterceptor.timeoutsubscriptions.md) - -## SearchInterceptor.timeoutSubscriptions property - -The subscriptions from scheduling the automatic timeout for each request. - -Signature: - -```typescript -protected timeoutSubscriptions: Subscription; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.http.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.http.md index 1146179c13d63..66c31bb6fcf80 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.http.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.http.md @@ -7,5 +7,5 @@ Signature: ```typescript -http: CoreStart['http']; +http: CoreSetup['http']; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md index 1291af5359887..63eb67ce48246 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md @@ -14,9 +14,9 @@ export interface SearchInterceptorDeps | Property | Type | Description | | --- | --- | --- | -| [application](./kibana-plugin-plugins-data-public.searchinterceptordeps.application.md) | ApplicationStart | | -| [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreStart['http'] | | -| [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsStart | | -| [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreStart['uiSettings'] | | +| [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreSetup['http'] | | +| [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | Promise<[CoreStart, any, unknown]> | | +| [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsSetup | | +| [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreSetup['uiSettings'] | | | [usageCollector](./kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md) | SearchUsageCollector | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.application.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md similarity index 61% rename from docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.application.md rename to docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md index a8cd1b170a595..855d0652058b8 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.application.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md @@ -1,11 +1,11 @@ -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [application](./kibana-plugin-plugins-data-public.searchinterceptordeps.application.md) +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) -## SearchInterceptorDeps.application property +## SearchInterceptorDeps.startServices property Signature: ```typescript -application: ApplicationStart; +startServices: Promise<[CoreStart, any, unknown]>; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md index 0023b34af10c3..1f560dfa5cf7c 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md @@ -7,5 +7,5 @@ Signature: ```typescript -toasts: ToastsStart; +toasts: ToastsSetup; ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md index 425e177ec9300..a34d223c34ac2 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md @@ -7,5 +7,5 @@ Signature: ```typescript -uiSettings: CoreStart['uiSettings']; +uiSettings: CoreSetup['uiSettings']; ``` diff --git a/src/plugins/data/public/mocks.ts b/src/plugins/data/public/mocks.ts index 135b6121d1dd5..3fc1e6454829d 100644 --- a/src/plugins/data/public/mocks.ts +++ b/src/plugins/data/public/mocks.ts @@ -44,6 +44,7 @@ const createSetupContract = (): Setup => { search: searchServiceMock.createSetupContract(), fieldFormats: fieldFormatsServiceMock.createSetupContract(), query: querySetupMock, + __enhance: jest.fn(), }; }; diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index c00496cffb441..2ef90c598007b 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -34,6 +34,7 @@ import { DataSetupDependencies, DataStartDependencies, InternalStartServices, + DataPublicPluginEnhancements, } from './types'; import { AutocompleteService } from './autocomplete'; import { SearchService } from './search/search_service'; @@ -157,16 +158,21 @@ export class DataPublicPlugin })) ); + const searchService = this.searchService.setup(core, { + expressions, + usageCollection, + getInternalStartServices, + packageInfo: this.packageInfo, + }); + return { autocomplete: this.autocomplete.setup(core), - search: this.searchService.setup(core, { - expressions, - usageCollection, - getInternalStartServices, - packageInfo: this.packageInfo, - }), + search: searchService, fieldFormats: this.fieldFormatsService.setup(core), query: queryService, + __enhance: (enhancements: DataPublicPluginEnhancements) => { + searchService.__enhance(enhancements.search); + }, }; } diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index a05f61b5c5adf..8ec45bc26913c 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -8,12 +8,12 @@ import { $Values } from '@kbn/utility-types'; import _ from 'lodash'; import { Action } from 'history'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; -import { ApplicationStart } from 'kibana/public'; import { Assign } from '@kbn/utility-types'; import { BehaviorSubject } from 'rxjs'; import Boom from 'boom'; import { Component } from 'react'; import { CoreSetup } from 'src/core/public'; +import { CoreSetup as CoreSetup_2 } from 'kibana/public'; import { CoreStart } from 'kibana/public'; import { CoreStart as CoreStart_2 } from 'src/core/public'; import { Ensure } from '@kbn/utility-types'; @@ -65,7 +65,7 @@ import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/ex import { Subscription } from 'rxjs'; import { Toast } from 'kibana/public'; import { ToastInputFields } from 'src/core/public/notifications'; -import { ToastsStart } from 'kibana/public'; +import { ToastsSetup } from 'kibana/public'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -222,6 +222,10 @@ export type CustomFilter = Filter & { // // @public (undocumented) export interface DataPublicPluginSetup { + // Warning: (ae-forgotten-export) The symbol "DataPublicPluginEnhancements" needs to be exported by the entry point index.d.ts + // + // @internal (undocumented) + __enhance: (enhancements: DataPublicPluginEnhancements) => void; // Warning: (ae-forgotten-export) The symbol "AutocompleteSetup" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -1724,15 +1728,19 @@ export interface SearchError { // @public (undocumented) export class SearchInterceptor { constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); + // @internal protected abortController: AbortController; + // @internal (undocumented) + protected application: CoreStart['application']; // (undocumented) protected readonly deps: SearchInterceptorDeps; - getPendingCount$: () => Observable; - // (undocumented) + getPendingCount$(): Observable; + // @internal (undocumented) protected hideToast: () => void; + // @internal protected longRunningToast?: Toast; + // @internal protected pendingCount$: BehaviorSubject; - protected pendingCount: number; // (undocumented) protected readonly requestTimeout?: number | undefined; // (undocumented) @@ -1743,8 +1751,9 @@ export class SearchInterceptor { combinedSignal: AbortSignal; cleanup: () => void; }; - // (undocumented) + // @internal (undocumented) protected showToast: () => void; + // @internal protected timeoutSubscriptions: Subscription; } @@ -1753,13 +1762,13 @@ export class SearchInterceptor { // @public (undocumented) export interface SearchInterceptorDeps { // (undocumented) - application: ApplicationStart; + http: CoreSetup_2['http']; // (undocumented) - http: CoreStart['http']; + startServices: Promise<[CoreStart, any, unknown]>; // (undocumented) - toasts: ToastsStart; + toasts: ToastsSetup; // (undocumented) - uiSettings: CoreStart['uiSettings']; + uiSettings: CoreSetup_2['uiSettings']; // Warning: (ae-forgotten-export) The symbol "SearchUsageCollector" needs to be exported by the entry point index.d.ts // // (undocumented) @@ -1990,9 +1999,9 @@ export const UI_SETTINGS: { // src/plugins/data/public/index.ts:393:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:45:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/types.ts:54:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/types.ts:55:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/types.ts:63:5 - (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/types.ts:62:5 - (ae-forgotten-export) The symbol "createFiltersFromValueClickAction" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/types.ts:63:5 - (ae-forgotten-export) The symbol "createFiltersFromRangeSelectAction" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/types.ts:71:5 - (ae-forgotten-export) The symbol "IndexPatternSelectProps" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/src/plugins/data/public/search/index.ts b/src/plugins/data/public/search/index.ts index 96445e5367147..ae028df31e401 100644 --- a/src/plugins/data/public/search/index.ts +++ b/src/plugins/data/public/search/index.ts @@ -21,7 +21,14 @@ export * from './aggs'; export * from './expressions'; export * from './tabify'; -export { ISearch, ISearchOptions, ISearchGeneric, ISearchSetup, ISearchStart } from './types'; +export { + ISearch, + ISearchOptions, + ISearchGeneric, + ISearchSetup, + ISearchStart, + SearchEnhancements, +} from './types'; export { IEsSearchResponse, IEsSearchRequest, ES_SEARCH_STRATEGY } from '../../common/search'; diff --git a/src/plugins/data/public/search/mocks.ts b/src/plugins/data/public/search/mocks.ts index c56331baffed2..8ccf46fe7c97d 100644 --- a/src/plugins/data/public/search/mocks.ts +++ b/src/plugins/data/public/search/mocks.ts @@ -26,13 +26,13 @@ export * from './search_source/mocks'; function createSetupContract(): jest.Mocked { return { aggs: searchAggsSetupMock(), + __enhance: jest.fn(), }; } function createStartContract(): jest.Mocked { return { aggs: searchAggsStartMock(), - setInterceptor: jest.fn(), search: jest.fn(), searchSource: searchSourceMock, __LEGACY: { diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index f4c5de2bcaf31..2eded17bda88c 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -17,27 +17,27 @@ * under the License. */ -import { CoreStart } from '../../../../core/public'; +import { CoreSetup } from '../../../../core/public'; import { coreMock } from '../../../../core/public/mocks'; import { IEsSearchRequest } from '../../common/search'; import { SearchInterceptor } from './search_interceptor'; import { AbortError } from '../../common'; let searchInterceptor: SearchInterceptor; -let mockCoreStart: MockedKeys; +let mockCoreSetup: MockedKeys; const flushPromises = () => new Promise((resolve) => setImmediate(resolve)); jest.useFakeTimers(); describe('SearchInterceptor', () => { beforeEach(() => { - mockCoreStart = coreMock.createStart(); + mockCoreSetup = coreMock.createSetup(); searchInterceptor = new SearchInterceptor( { - toasts: mockCoreStart.notifications.toasts, - application: mockCoreStart.application, - uiSettings: mockCoreStart.uiSettings, - http: mockCoreStart.http, + toasts: mockCoreSetup.notifications.toasts, + startServices: mockCoreSetup.getStartServices(), + uiSettings: mockCoreSetup.uiSettings, + http: mockCoreSetup.http, }, 1000 ); @@ -46,7 +46,7 @@ describe('SearchInterceptor', () => { describe('search', () => { test('Observable should resolve if fetch is successful', async () => { const mockResponse: any = { result: 200 }; - mockCoreStart.http.fetch.mockResolvedValueOnce(mockResponse); + mockCoreSetup.http.fetch.mockResolvedValueOnce(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; @@ -58,7 +58,7 @@ describe('SearchInterceptor', () => { test('Observable should fail if fetch has an error', async () => { const mockResponse: any = { result: 500 }; - mockCoreStart.http.fetch.mockRejectedValueOnce(mockResponse); + mockCoreSetup.http.fetch.mockRejectedValueOnce(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; @@ -72,7 +72,7 @@ describe('SearchInterceptor', () => { }); test('Observable should fail if fetch times out (test merged signal)', async () => { - mockCoreStart.http.fetch.mockImplementationOnce((options: any) => { + mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { return new Promise((resolve, reject) => { options.signal.addEventListener('abort', () => { reject(new AbortError()); @@ -100,7 +100,7 @@ describe('SearchInterceptor', () => { test('Observable should fail if user aborts (test merged signal)', async () => { const abortController = new AbortController(); - mockCoreStart.http.fetch.mockImplementationOnce((options: any) => { + mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { return new Promise((resolve, reject) => { options.signal.addEventListener('abort', () => { reject(new AbortError()); @@ -136,7 +136,7 @@ describe('SearchInterceptor', () => { const error = (e: any) => { expect(e).toBeInstanceOf(AbortError); - expect(mockCoreStart.http.fetch).not.toBeCalled(); + expect(mockCoreSetup.http.fetch).not.toBeCalled(); done(); }; response.subscribe({ error }); @@ -150,7 +150,7 @@ describe('SearchInterceptor', () => { pendingCount$.subscribe(pendingNext); const mockResponse: any = { result: 200 }; - mockCoreStart.http.fetch.mockResolvedValue(mockResponse); + mockCoreSetup.http.fetch.mockResolvedValue(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; @@ -169,7 +169,7 @@ describe('SearchInterceptor', () => { pendingCount$.subscribe(pendingNext); const mockResponse: any = { result: 500 }; - mockCoreStart.http.fetch.mockRejectedValue(mockResponse); + mockCoreSetup.http.fetch.mockRejectedValue(mockResponse); const mockRequest: IEsSearchRequest = { params: {}, }; diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index d6fcde8e986f3..99fccda7fddf3 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -20,7 +20,7 @@ import { trimEnd } from 'lodash'; import { BehaviorSubject, throwError, timer, Subscription, defer, from, Observable } from 'rxjs'; import { finalize, filter } from 'rxjs/operators'; -import { ApplicationStart, Toast, ToastsStart, CoreStart } from 'kibana/public'; +import { Toast, CoreStart, ToastsSetup, CoreSetup } from 'kibana/public'; import { getCombinedSignal, AbortError } from '../../common/utils'; import { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from '../../common/search'; import { ISearchOptions } from './types'; @@ -30,39 +30,43 @@ import { SearchUsageCollector } from './collectors'; const LONG_QUERY_NOTIFICATION_DELAY = 10000; export interface SearchInterceptorDeps { - toasts: ToastsStart; - application: ApplicationStart; - http: CoreStart['http']; - uiSettings: CoreStart['uiSettings']; + toasts: ToastsSetup; + http: CoreSetup['http']; + uiSettings: CoreSetup['uiSettings']; + startServices: Promise<[CoreStart, any, unknown]>; usageCollector?: SearchUsageCollector; } export class SearchInterceptor { /** * `abortController` used to signal all searches to abort. + * @internal */ protected abortController = new AbortController(); - /** - * The number of pending search requests. - */ - protected pendingCount = 0; - /** * Observable that emits when the number of pending requests changes. + * @internal */ - protected pendingCount$ = new BehaviorSubject(this.pendingCount); + protected pendingCount$ = new BehaviorSubject(0); /** * The subscriptions from scheduling the automatic timeout for each request. + * @internal */ protected timeoutSubscriptions: Subscription = new Subscription(); /** * The current long-running toast (if there is one). + * @internal */ protected longRunningToast?: Toast; + /** + * @internal + */ + protected application!: CoreStart['application']; + /** * This class should be instantiated with a `requestTimeout` corresponding with how many ms after * requests are initiated that they should automatically cancel. @@ -76,6 +80,10 @@ export class SearchInterceptor { ) { this.deps.http.addLoadingCountSource(this.pendingCount$); + this.deps.startServices.then(([coreStart]) => { + this.application = coreStart.application; + }); + // When search requests go out, a notification is scheduled allowing users to continue the // request past the timeout. When all search requests complete, we remove the notification. this.getPendingCount$() @@ -87,9 +95,9 @@ export class SearchInterceptor { * Returns an `Observable` over the current number of pending searches. This could mean that one * of the search requests is still in flight, or that it has only received partial responses. */ - public getPendingCount$ = () => { + public getPendingCount$() { return this.pendingCount$.asObservable(); - }; + } protected runSearch( request: IEsSearchRequest, @@ -112,7 +120,7 @@ export class SearchInterceptor { /** * Searches using the given `search` method. Overrides the `AbortSignal` with one that will abort * either when `cancelPending` is called, when the request times out, or when the original - * `AbortSignal` is aborted. Updates the `pendingCount` when the request is started/finalized. + * `AbortSignal` is aborted. Updates `pendingCount$` when the request is started/finalized. */ public search( request: IEsSearchRequest, @@ -125,11 +133,11 @@ export class SearchInterceptor { } const { combinedSignal, cleanup } = this.setupTimers(options); - this.pendingCount$.next(++this.pendingCount); + this.pendingCount$.next(this.pendingCount$.getValue() + 1); return this.runSearch(request, combinedSignal, options?.strategy).pipe( finalize(() => { - this.pendingCount$.next(--this.pendingCount); + this.pendingCount$.next(this.pendingCount$.getValue() - 1); cleanup(); }) ); @@ -173,13 +181,16 @@ export class SearchInterceptor { }; } + /** + * @internal + */ protected showToast = () => { if (this.longRunningToast) return; this.longRunningToast = this.deps.toasts.addInfo( { title: 'Your query is taking a while', text: getLongQueryNotification({ - application: this.deps.application, + application: this.application, }), }, { @@ -188,6 +199,9 @@ export class SearchInterceptor { ); }; + /** + * @internal + */ protected hideToast = () => { if (this.longRunningToast) { this.deps.toasts.remove(this.longRunningToast); @@ -198,3 +212,5 @@ export class SearchInterceptor { } }; } + +export type ISearchInterceptor = PublicMethodsOf; diff --git a/src/plugins/data/public/search/search_service.test.ts b/src/plugins/data/public/search/search_service.test.ts index 55d31db191733..f0a017847e06a 100644 --- a/src/plugins/data/public/search/search_service.test.ts +++ b/src/plugins/data/public/search/search_service.test.ts @@ -41,6 +41,7 @@ describe('Search service', () => { expressions: expressionsPluginMock.createSetupContract(), } as any); expect(setup).toHaveProperty('aggs'); + expect(setup).toHaveProperty('__enhance'); }); }); @@ -49,7 +50,6 @@ describe('Search service', () => { const start = searchService.start(mockCoreStart, { indexPatterns: {}, } as any); - expect(start).toHaveProperty('setInterceptor'); expect(start).toHaveProperty('search'); }); }); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 064e16014cb70..4c94925b66d6e 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -18,7 +18,7 @@ */ import { Plugin, CoreSetup, CoreStart, PackageInfo } from '../../../../core/public'; -import { ISearchSetup, ISearchStart } from './types'; +import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; import { ExpressionsSetup } from '../../../../plugins/expressions/public'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; @@ -28,7 +28,7 @@ import { calculateBounds, TimeRange } from '../../common/query'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; import { GetInternalStartServicesFn } from '../types'; -import { SearchInterceptor } from './search_interceptor'; +import { ISearchInterceptor, SearchInterceptor } from './search_interceptor'; import { getAggTypes, getAggTypesFunctions, @@ -54,7 +54,7 @@ interface SearchServiceStartDependencies { export class SearchService implements Plugin { private esClient?: LegacyApiCaller; private readonly aggTypesRegistry = new AggTypesRegistry(); - private searchInterceptor!: SearchInterceptor; + private searchInterceptor!: ISearchInterceptor; private usageCollector?: SearchUsageCollector; /** @@ -91,15 +91,6 @@ export class SearchService implements Plugin { const aggFunctions = getAggTypesFunctions(); aggFunctions.forEach((fn) => expressions.registerFunction(fn)); - return { - aggs: { - calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings), - types: aggTypesSetup, - }, - }; - } - - public start(core: CoreStart, dependencies: SearchServiceStartDependencies): ISearchStart { /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -109,14 +100,27 @@ export class SearchService implements Plugin { this.searchInterceptor = new SearchInterceptor( { toasts: core.notifications.toasts, - application: core.application, http: core.http, uiSettings: core.uiSettings, + startServices: core.getStartServices(), usageCollector: this.usageCollector!, }, core.injectedMetadata.getInjectedVar('esRequestTimeout') as number ); + return { + usageCollector: this.usageCollector!, + __enhance: (enhancements: SearchEnhancements) => { + this.searchInterceptor = enhancements.searchInterceptor; + }, + aggs: { + calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings), + types: aggTypesSetup, + }, + }; + } + + public start(core: CoreStart, dependencies: SearchServiceStartDependencies): ISearchStart { const aggTypesStart = this.aggTypesRegistry.start(); const search: ISearchGeneric = (request, options) => { @@ -145,17 +149,12 @@ export class SearchService implements Plugin { types: aggTypesStart, }, search, - usageCollector: this.usageCollector!, searchSource: { create: createSearchSource(dependencies.indexPatterns, searchSourceDependencies), createEmpty: () => { return new SearchSource({}, searchSourceDependencies); }, }, - setInterceptor: (searchInterceptor: SearchInterceptor) => { - // TODO: should an intercepror have a destroy method? - this.searchInterceptor = searchInterceptor; - }, __LEGACY: legacySearch, }; } diff --git a/src/plugins/data/public/search/types.ts b/src/plugins/data/public/search/types.ts index f80a13d048a68..d85d4c4e5c935 100644 --- a/src/plugins/data/public/search/types.ts +++ b/src/plugins/data/public/search/types.ts @@ -21,7 +21,7 @@ import { Observable } from 'rxjs'; import { PackageInfo } from 'kibana/server'; import { SearchAggsSetup, SearchAggsStart } from './aggs'; import { LegacyApiCaller } from './legacy/es_client'; -import { SearchInterceptor } from './search_interceptor'; +import { ISearchInterceptor } from './search_interceptor'; import { ISearchSource, SearchSourceFields } from './search_source'; import { SearchUsageCollector } from './collectors'; import { @@ -54,23 +54,33 @@ export interface ISearchStartLegacy { esClient: LegacyApiCaller; } +export interface SearchEnhancements { + searchInterceptor: ISearchInterceptor; +} /** * The setup contract exposed by the Search plugin exposes the search strategy extension * point. */ export interface ISearchSetup { aggs: SearchAggsSetup; + usageCollector?: SearchUsageCollector; + /** + * @internal + */ + __enhance: (enhancements: SearchEnhancements) => void; } export interface ISearchStart { aggs: SearchAggsStart; - setInterceptor: (searchInterceptor: SearchInterceptor) => void; search: ISearchGeneric; searchSource: { create: (fields?: SearchSourceFields) => Promise; createEmpty: () => ISearchSource; }; - usageCollector?: SearchUsageCollector; + /** + * @deprecated + * @internal + */ __LEGACY: ISearchStartLegacy; } diff --git a/src/plugins/data/public/types.ts b/src/plugins/data/public/types.ts index 6d67127251424..c39b7d355d495 100644 --- a/src/plugins/data/public/types.ts +++ b/src/plugins/data/public/types.ts @@ -25,13 +25,17 @@ import { UiActionsSetup, UiActionsStart } from 'src/plugins/ui_actions/public'; import { AutocompleteSetup, AutocompleteStart } from './autocomplete'; import { FieldFormatsSetup, FieldFormatsStart } from './field_formats'; import { createFiltersFromRangeSelectAction, createFiltersFromValueClickAction } from './actions'; -import { ISearchSetup, ISearchStart } from './search'; +import { ISearchSetup, ISearchStart, SearchEnhancements } from './search'; import { QuerySetup, QueryStart } from './query'; import { IndexPatternSelectProps } from './ui/index_pattern_select'; import { IndexPatternsContract } from './index_patterns'; import { StatefulSearchBarProps } from './ui/search_bar/create_search_bar'; import { UsageCollectionSetup } from '../../usage_collection/public'; +export interface DataPublicPluginEnhancements { + search: SearchEnhancements; +} + export interface DataSetupDependencies { expressions: ExpressionsSetup; uiActions: UiActionsSetup; @@ -47,6 +51,10 @@ export interface DataPublicPluginSetup { search: ISearchSetup; fieldFormats: FieldFormatsSetup; query: QuerySetup; + /** + * @internal + */ + __enhance: (enhancements: DataPublicPluginEnhancements) => void; } export interface DataPublicPluginStart { diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index bdf3f6a0acf90..7f6e3feac0671 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -31,20 +31,26 @@ export class DataEnhancedPlugin KUERY_LANGUAGE_NAME, setupKqlQuerySuggestionProvider(core) ); - } - public start(core: CoreStart, plugins: DataEnhancedStartDependencies) { - setAutocompleteService(plugins.data.autocomplete); const enhancedSearchInterceptor = new EnhancedSearchInterceptor( { toasts: core.notifications.toasts, - application: core.application, http: core.http, uiSettings: core.uiSettings, - usageCollector: plugins.data.search.usageCollector, + startServices: core.getStartServices(), + usageCollector: data.search.usageCollector, }, core.injectedMetadata.getInjectedVar('esRequestTimeout') as number ); - plugins.data.search.setInterceptor(enhancedSearchInterceptor); + + data.__enhance({ + search: { + searchInterceptor: enhancedSearchInterceptor, + }, + }); + } + + public start(core: CoreStart, plugins: DataEnhancedStartDependencies) { + setAutocompleteService(plugins.data.autocomplete); } } diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index d004511fa4674..fe954f1602cd3 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -6,7 +6,7 @@ import { coreMock } from '../../../../../src/core/public/mocks'; import { EnhancedSearchInterceptor } from './search_interceptor'; -import { CoreStart } from 'kibana/public'; +import { CoreSetup, CoreStart } from 'kibana/public'; import { AbortError } from '../../../../../src/plugins/data/common'; const timeTravel = (msToRun = 0) => { @@ -19,13 +19,14 @@ const error = jest.fn(); const complete = jest.fn(); let searchInterceptor: EnhancedSearchInterceptor; +let mockCoreSetup: MockedKeys; let mockCoreStart: MockedKeys; jest.useFakeTimers(); function mockFetchImplementation(responses: any[]) { let i = 0; - mockCoreStart.http.fetch.mockImplementation(() => { + mockCoreSetup.http.fetch.mockImplementation(() => { const { time = 0, value = {}, isError = false } = responses[i++]; return new Promise((resolve, reject) => setTimeout(() => { @@ -39,6 +40,7 @@ describe('EnhancedSearchInterceptor', () => { let mockUsageCollector: any; beforeEach(() => { + mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); next.mockClear(); @@ -54,12 +56,20 @@ describe('EnhancedSearchInterceptor', () => { trackLongQueryRunBeyondTimeout: jest.fn(), }; + const mockPromise = new Promise((resolve) => { + resolve([ + { + application: mockCoreStart.application, + }, + ]); + }); + searchInterceptor = new EnhancedSearchInterceptor( { - toasts: mockCoreStart.notifications.toasts, - application: mockCoreStart.application, - http: mockCoreStart.http, - uiSettings: mockCoreStart.uiSettings, + toasts: mockCoreSetup.notifications.toasts, + startServices: mockPromise as any, + http: mockCoreSetup.http, + uiSettings: mockCoreSetup.uiSettings, usageCollector: mockUsageCollector, }, 1000 @@ -229,8 +239,8 @@ describe('EnhancedSearchInterceptor', () => { expect(error).toHaveBeenCalled(); expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError); - expect(mockCoreStart.http.fetch).toHaveBeenCalledTimes(2); - expect(mockCoreStart.http.delete).toHaveBeenCalled(); + expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2); + expect(mockCoreSetup.http.delete).toHaveBeenCalled(); }); test('should not DELETE a running async search on async timeout prior to first response', async () => { @@ -253,8 +263,8 @@ describe('EnhancedSearchInterceptor', () => { expect(error).toHaveBeenCalled(); expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError); - expect(mockCoreStart.http.fetch).toHaveBeenCalled(); - expect(mockCoreStart.http.delete).not.toHaveBeenCalled(); + expect(mockCoreSetup.http.fetch).toHaveBeenCalled(); + expect(mockCoreSetup.http.delete).not.toHaveBeenCalled(); }); test('should DELETE a running async search on async timeout after first response', async () => { @@ -285,16 +295,16 @@ describe('EnhancedSearchInterceptor', () => { expect(next).toHaveBeenCalled(); expect(error).not.toHaveBeenCalled(); - expect(mockCoreStart.http.fetch).toHaveBeenCalled(); - expect(mockCoreStart.http.delete).not.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 await timeTravel(1000); expect(error).toHaveBeenCalled(); expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError); - expect(mockCoreStart.http.fetch).toHaveBeenCalledTimes(2); - expect(mockCoreStart.http.delete).toHaveBeenCalled(); + expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2); + expect(mockCoreSetup.http.delete).toHaveBeenCalled(); }); test('should DELETE a running async search on async timeout on error from fetch', async () => { @@ -327,16 +337,16 @@ describe('EnhancedSearchInterceptor', () => { expect(next).toHaveBeenCalled(); expect(error).not.toHaveBeenCalled(); - expect(mockCoreStart.http.fetch).toHaveBeenCalled(); - expect(mockCoreStart.http.delete).not.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 await timeTravel(10); expect(error).toHaveBeenCalled(); expect(error.mock.calls[0][0]).toBe(responses[1].value); - expect(mockCoreStart.http.fetch).toHaveBeenCalledTimes(2); - expect(mockCoreStart.http.delete).toHaveBeenCalled(); + expect(mockCoreSetup.http.fetch).toHaveBeenCalledTimes(2); + expect(mockCoreSetup.http.delete).toHaveBeenCalled(); }); }); @@ -367,7 +377,7 @@ describe('EnhancedSearchInterceptor', () => { await timeTravel(); - const areAllRequestsAborted = mockCoreStart.http.fetch.mock.calls.every( + const areAllRequestsAborted = mockCoreSetup.http.fetch.mock.calls.every( ([{ signal }]) => signal?.aborted ); expect(areAllRequestsAborted).toBe(true); diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index bff9e2cb9048c..ae6dddf33536f 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -20,8 +20,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { /** * This class should be instantiated with a `requestTimeout` corresponding with how many ms after * requests are initiated that they should automatically cancel. - * @param toasts The `core.notifications.toasts` service - * @param application The `core.application` service + * @param deps `SearchInterceptorDeps` * @param requestTimeout Usually config value `elasticsearch.requestTimeout` */ constructor(deps: SearchInterceptorDeps, requestTimeout?: number) { @@ -78,7 +77,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { const { combinedSignal, cleanup } = this.setupTimers(options); const aborted$ = from(toPromise(combinedSignal)); - this.pendingCount$.next(++this.pendingCount); + this.pendingCount$.next(this.pendingCount$.getValue() + 1); return this.runSearch(request, combinedSignal, options?.strategy).pipe( expand((response) => { @@ -113,7 +112,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { }, }), finalize(() => { - this.pendingCount$.next(--this.pendingCount); + this.pendingCount$.next(this.pendingCount$.getValue() - 1); cleanup(); }) );