Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[data.search] Server-side background session service #81099

Merged
merged 42 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
26c47bd
[Search] Add request context and asScoped pattern
lukasolson Oct 15, 2020
36b8fcb
Update docs
lukasolson Oct 15, 2020
8274226
Merge branch 'master' into search-as-scoped
lukasolson Oct 16, 2020
c7296f0
Unify interface for getting search client
lukasolson Oct 19, 2020
d77c009
[WIP] [data.search] Server-side background session service
lukasolson Oct 20, 2020
9dadfb2
Update examples/search_examples/server/my_strategy.ts
lukasolson Oct 20, 2020
ab55bcb
Merge branch 'master' into search-as-scoped
lukasolson Oct 26, 2020
2b3d2a0
Review feedback
lukasolson Oct 26, 2020
7a048a0
Merge branch 'search-as-scoped' of github.com:lukasolson/kibana into …
lukasolson Oct 26, 2020
2d0da67
Merge branch 'master' into search-as-scoped
lukasolson Oct 27, 2020
f7cb5a1
Merge branch 'master' into search-as-scoped
lukasolson Oct 28, 2020
6c9aec5
Fix checks
lukasolson Oct 28, 2020
5b9b0c9
Merge branch 'search-as-scoped' into search-server-session
lukasolson Oct 28, 2020
260e46c
Add tapFirst and additional props for session
lukasolson Oct 28, 2020
1ae55ef
Fix CI
lukasolson Oct 29, 2020
4634fb4
Fix security search
lukasolson Oct 29, 2020
c35fb49
Merge branch 'master' into search-as-scoped
lukasolson Oct 30, 2020
1567995
Merge branch 'master' into search-as-scoped
lukasolson Nov 2, 2020
5f7c9ab
Fix test
lukasolson Nov 2, 2020
f1b515d
Fix test for reals
lukasolson Nov 2, 2020
a1d67ae
Merge branch 'master' into search-server-session
lukasolson Nov 2, 2020
9dbd645
Merge branch 'search-as-scoped' into search-server-session
lukasolson Nov 2, 2020
e32a435
Add restore method
lukasolson Nov 3, 2020
b1ece61
Merge branch 'master' into search-server-session
lukasolson Nov 4, 2020
6f3e33c
Merge branch 'master' into search-server-session
lukasolson Nov 9, 2020
71d5bd8
Add code to search examples
lukasolson Nov 9, 2020
8fbe317
Add restore and search using restored ID
lukasolson Nov 10, 2020
fda7a79
Fix handling of preference and order of params
lukasolson Nov 11, 2020
e06d8da
Merge branch 'master' into search-server-session
lukasolson Nov 11, 2020
c24f83d
Trim & cleanup
lukasolson Nov 12, 2020
0b10e22
Fix types
lukasolson Nov 12, 2020
700f2a0
Review feedback
lukasolson Nov 12, 2020
0f34c4c
Add tests and remove handling of username
lukasolson Nov 12, 2020
c4e63c2
Update docs
lukasolson Nov 12, 2020
5c15656
Merge branch 'master' into search-server-session
lukasolson Nov 16, 2020
06e83fb
Move utils to server
lukasolson Nov 16, 2020
967214d
Review feedback
lukasolson Nov 18, 2020
645146b
Merge branch 'master' into search-server-session
kibanamachine Nov 18, 2020
dc6104c
More review feedback
lukasolson Nov 18, 2020
8d81f39
Regenerate docs
lukasolson Nov 18, 2020
9bbfa3a
Review feedback
lukasolson Nov 18, 2020
a3dc0d8
Doc changes
lukasolson Nov 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISearchOptions](./kibana-plugin-plugins-data-public.isearchoptions.md) &gt; [isRestore](./kibana-plugin-plugins-data-public.isearchoptions.isrestore.md)

## ISearchOptions.isRestore property

Whether the session is restored (i.e. search requests should re-use the stored search IDs, rather than starting from scratch)

<b>Signature:</b>

```typescript
isRestore?: boolean;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISearchOptions](./kibana-plugin-plugins-data-public.isearchoptions.md) &gt; [isStored](./kibana-plugin-plugins-data-public.isearchoptions.isstored.md)

## ISearchOptions.isStored property

Whether the session is already saved (i.e. sent to background)

<b>Signature:</b>

```typescript
isStored?: boolean;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface ISearchOptions
| Property | Type | Description |
| --- | --- | --- |
| [abortSignal](./kibana-plugin-plugins-data-public.isearchoptions.abortsignal.md) | <code>AbortSignal</code> | An <code>AbortSignal</code> that allows the caller of <code>search</code> to abort a search request. |
| [isRestore](./kibana-plugin-plugins-data-public.isearchoptions.isrestore.md) | <code>boolean</code> | Whether the session is restored (i.e. search requests should re-use the stored search IDs, rather than starting from scratch) |
| [isStored](./kibana-plugin-plugins-data-public.isearchoptions.isstored.md) | <code>boolean</code> | Whether the session is already saved (i.e. sent to background) |
| [sessionId](./kibana-plugin-plugins-data-public.isearchoptions.sessionid.md) | <code>string</code> | A session ID, grouping multiple search requests into a single session. |
| [strategy](./kibana-plugin-plugins-data-public.isearchoptions.strategy.md) | <code>string</code> | Use this option to force using a specific server side search strategy. Leave empty to use the default strategy. |

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [delete](./kibana-plugin-plugins-data-public.isessionservice.delete.md)

## ISessionService.delete property

Deletes a session

<b>Signature:</b>

```typescript
delete: (sessionId: string) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [find](./kibana-plugin-plugins-data-public.isessionservice.find.md)

## ISessionService.find property

Gets a list of saved sessions

<b>Signature:</b>

```typescript
find: (options: SearchSessionFindOptions) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [get](./kibana-plugin-plugins-data-public.isessionservice.get.md)

## ISessionService.get property

Gets a saved session

<b>Signature:</b>

```typescript
get: (sessionId: string) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [isRestore](./kibana-plugin-plugins-data-public.isessionservice.isrestore.md)

## ISessionService.isRestore property

Whether the active session is restored (i.e. reusing previous search IDs)

<b>Signature:</b>

```typescript
isRestore: () => boolean;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [isStored](./kibana-plugin-plugins-data-public.isessionservice.isstored.md)

## ISessionService.isStored property

Whether the active session is already saved (i.e. sent to background)

<b>Signature:</b>

```typescript
isStored: () => boolean;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,15 @@ export interface ISessionService
| Property | Type | Description |
| --- | --- | --- |
| [clear](./kibana-plugin-plugins-data-public.isessionservice.clear.md) | <code>() =&gt; void</code> | Clears the active session. |
| [delete](./kibana-plugin-plugins-data-public.isessionservice.delete.md) | <code>(sessionId: string) =&gt; Promise&lt;any&gt;</code> | Deletes a session |
| [find](./kibana-plugin-plugins-data-public.isessionservice.find.md) | <code>(options: SearchSessionFindOptions) =&gt; Promise&lt;any&gt;</code> | Gets a list of saved sessions |
| [get](./kibana-plugin-plugins-data-public.isessionservice.get.md) | <code>(sessionId: string) =&gt; Promise&lt;any&gt;</code> | Gets a saved session |
| [getSession$](./kibana-plugin-plugins-data-public.isessionservice.getsession_.md) | <code>() =&gt; Observable&lt;string &#124; undefined&gt;</code> | Returns the observable that emits an update every time the session ID changes |
| [getSessionId](./kibana-plugin-plugins-data-public.isessionservice.getsessionid.md) | <code>() =&gt; string &#124; undefined</code> | Returns the active session ID |
| [restore](./kibana-plugin-plugins-data-public.isessionservice.restore.md) | <code>(sessionId: string) =&gt; void</code> | Restores existing session |
| [isRestore](./kibana-plugin-plugins-data-public.isessionservice.isrestore.md) | <code>() =&gt; boolean</code> | Whether the active session is restored (i.e. reusing previous search IDs) |
| [isStored](./kibana-plugin-plugins-data-public.isessionservice.isstored.md) | <code>() =&gt; boolean</code> | Whether the active session is already saved (i.e. sent to background) |
| [restore](./kibana-plugin-plugins-data-public.isessionservice.restore.md) | <code>(sessionId: string) =&gt; Promise&lt;any&gt;</code> | Restores existing session |
| [save](./kibana-plugin-plugins-data-public.isessionservice.save.md) | <code>(name: string, url: string) =&gt; Promise&lt;any&gt;</code> | Saves a session |
| [start](./kibana-plugin-plugins-data-public.isessionservice.start.md) | <code>() =&gt; string</code> | Starts a new session |
| [update](./kibana-plugin-plugins-data-public.isessionservice.update.md) | <code>(sessionId: string, attributes: Partial&lt;BackgroundSessionSavedObjectAttributes&gt;) =&gt; Promise&lt;any&gt;</code> | Updates a session |

Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Restores existing session
<b>Signature:</b>

```typescript
restore: (sessionId: string) => void;
restore: (sessionId: string) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [save](./kibana-plugin-plugins-data-public.isessionservice.save.md)

## ISessionService.save property

Saves a session

<b>Signature:</b>

```typescript
save: (name: string, url: string) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ISessionService](./kibana-plugin-plugins-data-public.isessionservice.md) &gt; [update](./kibana-plugin-plugins-data-public.isessionservice.update.md)

## ISessionService.update property

Updates a session

<b>Signature:</b>

```typescript
update: (sessionId: string, attributes: Partial<BackgroundSessionSavedObjectAttributes>) => Promise<any>;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [ISearchOptions](./kibana-plugin-plugins-data-server.isearchoptions.md) &gt; [isRestore](./kibana-plugin-plugins-data-server.isearchoptions.isrestore.md)

## ISearchOptions.isRestore property

Whether the session is restored (i.e. search requests should re-use the stored search IDs, rather than starting from scratch)

<b>Signature:</b>

```typescript
isRestore?: boolean;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [ISearchOptions](./kibana-plugin-plugins-data-server.isearchoptions.md) &gt; [isStored](./kibana-plugin-plugins-data-server.isearchoptions.isstored.md)

## ISearchOptions.isStored property

Whether the session is already saved (i.e. sent to background)

<b>Signature:</b>

```typescript
isStored?: boolean;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface ISearchOptions
| Property | Type | Description |
| --- | --- | --- |
| [abortSignal](./kibana-plugin-plugins-data-server.isearchoptions.abortsignal.md) | <code>AbortSignal</code> | An <code>AbortSignal</code> that allows the caller of <code>search</code> to abort a search request. |
| [isRestore](./kibana-plugin-plugins-data-server.isearchoptions.isrestore.md) | <code>boolean</code> | Whether the session is restored (i.e. search requests should re-use the stored search IDs, rather than starting from scratch) |
| [isStored](./kibana-plugin-plugins-data-server.isearchoptions.isstored.md) | <code>boolean</code> | Whether the session is already saved (i.e. sent to background) |
| [sessionId](./kibana-plugin-plugins-data-server.isearchoptions.sessionid.md) | <code>string</code> | A session ID, grouping multiple search requests into a single session. |
| [strategy](./kibana-plugin-plugins-data-server.isearchoptions.strategy.md) | <code>string</code> | Use this option to force using a specific server side search strategy. Leave empty to use the default strategy. |

2 changes: 1 addition & 1 deletion examples/search_examples/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "8.0.0",
"server": true,
"ui": true,
"requiredPlugins": ["navigation", "data", "developerExamples"],
"requiredPlugins": ["navigation", "data", "developerExamples", "kibanaUtils"],
"optionalPlugins": [],
"requiredBundles": []
}
1 change: 1 addition & 0 deletions src/plugins/data/common/search/session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@
* under the License.
*/

export * from './status';
export * from './types';
7 changes: 7 additions & 0 deletions src/plugins/data/common/search/session/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,12 @@ export function getSessionServiceMock(): jest.Mocked<ISessionService> {
restore: jest.fn(),
getSessionId: jest.fn(),
getSession$: jest.fn(() => new BehaviorSubject(undefined).asObservable()),
isStored: jest.fn(),
isRestore: jest.fn(),
save: jest.fn(),
get: jest.fn(),
find: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
};
}
26 changes: 26 additions & 0 deletions src/plugins/data/common/search/session/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.
*/

export enum BackgroundSessionStatus {
INCOMPLETE = 'incomplete',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

//nit IN_PROGRESS?

ERROR = 'error',
COMPLETE = 'complete',
CANCELLED = 'cancelled',
EXPIRED = 'expired',
}
61 changes: 60 additions & 1 deletion src/plugins/data/common/search/session/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/

import { Observable } from 'rxjs';
import type { SavedObject, SavedObjectsFindResponse } from 'kibana/server';

export interface ISessionService {
/**
Expand All @@ -30,6 +31,17 @@ export interface ISessionService {
* @returns `Observable`
*/
getSession$: () => Observable<string | undefined>;

/**
* Whether the active session is already saved (i.e. sent to background)
*/
isStored: () => boolean;

/**
* Whether the active session is restored (i.e. reusing previous search IDs)
*/
isRestore: () => boolean;

/**
* Starts a new session
*/
Expand All @@ -38,10 +50,57 @@ export interface ISessionService {
/**
* Restores existing session
*/
restore: (sessionId: string) => void;
restore: (sessionId: string) => Promise<SavedObject<BackgroundSessionSavedObjectAttributes>>;

/**
* Clears the active session.
*/
clear: () => void;

/**
* Saves a session
*/
save: (name: string, url: string) => Promise<SavedObject<BackgroundSessionSavedObjectAttributes>>;

/**
* Gets a saved session
*/
get: (sessionId: string) => Promise<SavedObject<BackgroundSessionSavedObjectAttributes>>;

/**
* Gets a list of saved sessions
*/
find: (
options: SearchSessionFindOptions
) => Promise<SavedObjectsFindResponse<BackgroundSessionSavedObjectAttributes>>;

/**
* Updates a session
*/
update: (
sessionId: string,
attributes: Partial<BackgroundSessionSavedObjectAttributes>
) => Promise<any>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would would be the proper return types for this CRUD methods?
I can add in follow up client side PR, just not sure what are those.


/**
* Deletes a session
*/
delete: (sessionId: string) => Promise<any>;
Copy link
Contributor

@lizozom lizozom Nov 18, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns Promise<boolean>?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, probably Promise<void> since an unsuccessful delete will throw.

}

export interface BackgroundSessionSavedObjectAttributes {
name: string;
url: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thing we shouldn't have a URL, but an app name and two sets of parameters generated using the URL Generator (original and restore URLs)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you okay with leaving this to the PR that integrates with the URL generator? If you prefer, I can leave out the url portion altogether from this PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets leave it out then

created: string;
expires: string;
status: string;
idMapping: Record<string, string>;
}

export interface SearchSessionFindOptions {
page?: number;
perPage?: number;
sortField?: string;
sortOrder?: string;
filter?: string;
}
11 changes: 11 additions & 0 deletions src/plugins/data/common/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,15 @@ export interface ISearchOptions {
* A session ID, grouping multiple search requests into a single session.
*/
sessionId?: string;

/**
* Whether the session is already saved (i.e. sent to background)
*/
isStored?: boolean;

/**
* Whether the session is restored (i.e. search requests should re-use the stored search IDs,
* rather than starting from scratch)
*/
isRestore?: boolean;
}
1 change: 1 addition & 0 deletions src/plugins/data/common/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@

/** @internal */
export { shortenDottedString } from './shorten_dotted_string';
export { tapFirst } from './tap_first';
30 changes: 30 additions & 0 deletions src/plugins/data/common/utils/tap_first.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 { of } from 'rxjs';
import { tapFirst } from './tap_first';

describe('tapFirst', () => {
it('should tap the first and only the first', () => {
const fn = jest.fn();
of(1, 2, 3).pipe(tapFirst(fn)).subscribe();
expect(fn).toBeCalledTimes(1);
expect(fn).lastCalledWith(1);
});
});
Loading