diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
index ae433e3db14c6..b10ad949c4944 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md
@@ -106,6 +106,7 @@ readonly links: {
};
readonly search: {
readonly sessions: string;
+ readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
index b0800c7dfc65e..c020f57faa882 100644
--- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
+++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md
@@ -17,5 +17,5 @@ export interface DocLinksStart
| --- | --- | --- |
| [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string
| |
| [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string
| |
-| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
}>;
}
| |
+| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
};
readonly auditbeat: {
readonly base: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly guide: string;
readonly gettingStarted: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Record<string, string>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
}
| |
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrestored.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrestored.md
new file mode 100644
index 0000000000000..d649212ae0547
--- /dev/null
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.isrestored.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IKibanaSearchResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.md) > [isRestored](./kibana-plugin-plugins-data-public.ikibanasearchresponse.isrestored.md)
+
+## IKibanaSearchResponse.isRestored property
+
+Indicates whether the results returned are from the async-search index
+
+Signature:
+
+```typescript
+isRestored?: boolean;
+```
diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md
index 1d3e0c08dfc18..c7046902dac72 100644
--- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md
+++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ikibanasearchresponse.md
@@ -16,6 +16,7 @@ export interface IKibanaSearchResponse
| --- | --- | --- |
| [id](./kibana-plugin-plugins-data-public.ikibanasearchresponse.id.md) | string
| Some responses may contain a unique id to identify the request this response came from. |
| [isPartial](./kibana-plugin-plugins-data-public.ikibanasearchresponse.ispartial.md) | boolean
| Indicates whether the results returned are complete or partial |
+| [isRestored](./kibana-plugin-plugins-data-public.ikibanasearchresponse.isrestored.md) | boolean
| Indicates whether the results returned are from the async-search index |
| [isRunning](./kibana-plugin-plugins-data-public.ikibanasearchresponse.isrunning.md) | boolean
| Indicates whether search is still in flight |
| [loaded](./kibana-plugin-plugins-data-public.ikibanasearchresponse.loaded.md) | number
| If relevant to the search strategy, return a loaded number that represents how progress is indicated. |
| [rawResponse](./kibana-plugin-plugins-data-public.ikibanasearchresponse.rawresponse.md) | RawResponse
| The raw response returned by the internal search method (usually the raw ES response) |
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
index b1745b298e27e..9816b884c4614 100644
--- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md
@@ -13,6 +13,7 @@
| [IndexPatternsFetcher](./kibana-plugin-plugins-data-server.indexpatternsfetcher.md) | |
| [IndexPatternsService](./kibana-plugin-plugins-data-server.indexpatternsservice.md) | |
| [IndexPatternsServiceProvider](./kibana-plugin-plugins-data-server.indexpatternsserviceprovider.md) | |
+| [NoSearchIdInSessionError](./kibana-plugin-plugins-data-server.nosearchidinsessionerror.md) | |
| [OptionedParamType](./kibana-plugin-plugins-data-server.optionedparamtype.md) | |
| [Plugin](./kibana-plugin-plugins-data-server.plugin.md) | |
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror._constructor_.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror._constructor_.md
new file mode 100644
index 0000000000000..e48a1c98f8578
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror._constructor_.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [NoSearchIdInSessionError](./kibana-plugin-plugins-data-server.nosearchidinsessionerror.md) > [(constructor)](./kibana-plugin-plugins-data-server.nosearchidinsessionerror._constructor_.md)
+
+## NoSearchIdInSessionError.(constructor)
+
+Constructs a new instance of the `NoSearchIdInSessionError` class
+
+Signature:
+
+```typescript
+constructor();
+```
diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror.md
new file mode 100644
index 0000000000000..707739f845cd1
--- /dev/null
+++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.nosearchidinsessionerror.md
@@ -0,0 +1,18 @@
+
+
+[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [NoSearchIdInSessionError](./kibana-plugin-plugins-data-server.nosearchidinsessionerror.md)
+
+## NoSearchIdInSessionError class
+
+Signature:
+
+```typescript
+export declare class NoSearchIdInSessionError extends KbnError
+```
+
+## Constructors
+
+| Constructor | Modifiers | Description |
+| --- | --- | --- |
+| [(constructor)()](./kibana-plugin-plugins-data-server.nosearchidinsessionerror._constructor_.md) | | Constructs a new instance of the NoSearchIdInSessionError
class |
+
diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts
index c737f41cdabc5..f19ae2d9af3c2 100644
--- a/src/core/public/doc_links/doc_links_service.ts
+++ b/src/core/public/doc_links/doc_links_service.ts
@@ -205,6 +205,7 @@ export class DocLinksService {
},
search: {
sessions: `${KIBANA_DOCS}search-sessions.html`,
+ sessionLimits: `${KIBANA_DOCS}search-sessions.html#_limitations`,
},
date: {
dateMath: `${ELASTICSEARCH_DOCS}common-options.html#date-math`,
@@ -525,6 +526,7 @@ export interface DocLinksStart {
};
readonly search: {
readonly sessions: string;
+ readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md
index 27569935bcc65..31e85341fb519 100644
--- a/src/core/public/public.api.md
+++ b/src/core/public/public.api.md
@@ -585,6 +585,7 @@ export interface DocLinksStart {
};
readonly search: {
readonly sessions: string;
+ readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
diff --git a/src/plugins/data/common/search/types.ts b/src/plugins/data/common/search/types.ts
index d1890ec97df4e..c5cf3f9f09e6c 100644
--- a/src/plugins/data/common/search/types.ts
+++ b/src/plugins/data/common/search/types.ts
@@ -65,6 +65,11 @@ export interface IKibanaSearchResponse {
*/
isPartial?: boolean;
+ /**
+ * Indicates whether the results returned are from the async-search index
+ */
+ isRestored?: boolean;
+
/**
* The raw response returned by the internal search method (usually the raw ES response)
*/
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 8e2f28d75166a..9076b0a5770f1 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -1353,6 +1353,7 @@ export interface IKibanaSearchRequest {
export interface IKibanaSearchResponse {
id?: string;
isPartial?: boolean;
+ isRestored?: boolean;
isRunning?: boolean;
loaded?: number;
rawResponse: RawResponse;
diff --git a/src/plugins/data/public/search/errors/index.ts b/src/plugins/data/public/search/errors/index.ts
index 82c9e04b79798..fcdea8dec1c2e 100644
--- a/src/plugins/data/public/search/errors/index.ts
+++ b/src/plugins/data/public/search/errors/index.ts
@@ -12,3 +12,4 @@ export * from './timeout_error';
export * from './utils';
export * from './types';
export * from './http_error';
+export * from './search_session_incomplete_warning';
diff --git a/src/plugins/data/public/search/errors/search_session_incomplete_warning.tsx b/src/plugins/data/public/search/errors/search_session_incomplete_warning.tsx
new file mode 100644
index 0000000000000..c5c5c37f31cf8
--- /dev/null
+++ b/src/plugins/data/public/search/errors/search_session_incomplete_warning.tsx
@@ -0,0 +1,31 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
+import { CoreStart } from 'kibana/public';
+import React from 'react';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+export const SearchSessionIncompleteWarning = (docLinks: CoreStart['docLinks']) => (
+ <>
+
+ It needs more time to fully render. You can wait here or come back to it later.
+
+
+
+
+
+
+ >
+);
diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts
index fe66d4b6e9937..155638250a2a4 100644
--- a/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts
+++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.test.ts
@@ -29,6 +29,12 @@ jest.mock('./utils', () => ({
}),
}));
+jest.mock('../errors/search_session_incomplete_warning', () => ({
+ SearchSessionIncompleteWarning: jest.fn(),
+}));
+
+import { SearchSessionIncompleteWarning } from '../errors/search_session_incomplete_warning';
+
let searchInterceptor: SearchInterceptor;
let mockCoreSetup: MockedKeys;
let bfetchSetup: jest.Mocked;
@@ -508,6 +514,7 @@ describe('SearchInterceptor', () => {
}
: null
);
+ sessionServiceMock.isRestore.mockReturnValue(!!opts?.isRestore);
fetchMock.mockResolvedValue({ result: 200 });
};
@@ -562,6 +569,92 @@ describe('SearchInterceptor', () => {
(sessionService as jest.Mocked).getSearchOptions
).toHaveBeenCalledWith(sessionId);
});
+
+ test('should not show warning if a search is available during restore', async () => {
+ setup({
+ isRestore: true,
+ isStored: true,
+ sessionId: '123',
+ });
+
+ const responses = [
+ {
+ time: 10,
+ value: {
+ isPartial: false,
+ isRunning: false,
+ isRestored: true,
+ id: 1,
+ rawResponse: {
+ took: 1,
+ },
+ },
+ },
+ ];
+ mockFetchImplementation(responses);
+
+ const response = searchInterceptor.search(
+ {},
+ {
+ sessionId: '123',
+ }
+ );
+ response.subscribe({ next, error, complete });
+
+ await timeTravel(10);
+
+ expect(SearchSessionIncompleteWarning).toBeCalledTimes(0);
+ });
+
+ test('should show warning once if a search is not available during restore', async () => {
+ setup({
+ isRestore: true,
+ isStored: true,
+ sessionId: '123',
+ });
+
+ const responses = [
+ {
+ time: 10,
+ value: {
+ isPartial: false,
+ isRunning: false,
+ isRestored: false,
+ id: 1,
+ rawResponse: {
+ took: 1,
+ },
+ },
+ },
+ ];
+ mockFetchImplementation(responses);
+
+ searchInterceptor
+ .search(
+ {},
+ {
+ sessionId: '123',
+ }
+ )
+ .subscribe({ next, error, complete });
+
+ await timeTravel(10);
+
+ expect(SearchSessionIncompleteWarning).toBeCalledTimes(1);
+
+ searchInterceptor
+ .search(
+ {},
+ {
+ sessionId: '123',
+ }
+ )
+ .subscribe({ next, error, complete });
+
+ await timeTravel(10);
+
+ expect(SearchSessionIncompleteWarning).toBeCalledTimes(1);
+ });
});
describe('Session tracking', () => {
diff --git a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts
index 57b156a9b3c00..e0e1df65101c7 100644
--- a/src/plugins/data/public/search/search_interceptor/search_interceptor.ts
+++ b/src/plugins/data/public/search/search_interceptor/search_interceptor.ts
@@ -43,6 +43,7 @@ import {
PainlessError,
SearchTimeoutError,
TimeoutErrorMode,
+ SearchSessionIncompleteWarning,
} from '../errors';
import { toMountPoint } from '../../../../kibana_react/public';
import { AbortError, KibanaServerError } from '../../../../kibana_utils/public';
@@ -82,6 +83,7 @@ export class SearchInterceptor {
* @internal
*/
private application!: CoreStart['application'];
+ private docLinks!: CoreStart['docLinks'];
private batchedFetch!: BatchedFunc<
{ request: IKibanaSearchRequest; options: ISearchOptionsSerializable },
IKibanaSearchResponse
@@ -95,6 +97,7 @@ export class SearchInterceptor {
this.deps.startServices.then(([coreStart]) => {
this.application = coreStart.application;
+ this.docLinks = coreStart.docLinks;
});
this.batchedFetch = deps.bfetch.batchedFunction({
@@ -345,6 +348,11 @@ export class SearchInterceptor {
this.handleSearchError(e, searchOptions, searchAbortController.isTimeout())
);
}),
+ tap((response) => {
+ if (this.deps.session.isRestore() && response.isRestored === false) {
+ this.showRestoreWarning(this.deps.session.getSessionId());
+ }
+ }),
finalize(() => {
this.pendingCount$.next(this.pendingCount$.getValue() - 1);
if (untrackSearch && this.deps.session.isCurrentSession(sessionId)) {
@@ -371,6 +379,25 @@ export class SearchInterceptor {
}
);
+ private showRestoreWarningToast = (sessionId?: string) => {
+ this.deps.toasts.addWarning(
+ {
+ title: 'Your search session is still running',
+ text: toMountPoint(SearchSessionIncompleteWarning(this.docLinks)),
+ },
+ {
+ toastLifeTimeMs: 60000,
+ }
+ );
+ };
+
+ private showRestoreWarning = memoize(
+ this.showRestoreWarningToast,
+ (_: SearchTimeoutError, sessionId: string) => {
+ return sessionId;
+ }
+ );
+
/**
* Show one error notification per session.
* @internal
diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts
index 0764f4f441e42..dd60951e6d228 100644
--- a/src/plugins/data/server/index.ts
+++ b/src/plugins/data/server/index.ts
@@ -238,6 +238,7 @@ export {
DataRequestHandlerContext,
AsyncSearchResponse,
AsyncSearchStatusResponse,
+ NoSearchIdInSessionError,
} from './search';
// Search namespace
diff --git a/src/plugins/data/server/search/errors/no_search_id_in_session.ts b/src/plugins/data/server/search/errors/no_search_id_in_session.ts
new file mode 100644
index 0000000000000..b291df1cee5ba
--- /dev/null
+++ b/src/plugins/data/server/search/errors/no_search_id_in_session.ts
@@ -0,0 +1,15 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { KbnError } from '../../../../kibana_utils/common';
+
+export class NoSearchIdInSessionError extends KbnError {
+ constructor() {
+ super('No search ID in this session matching the given search request');
+ }
+}
diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts
index 812f3171aef99..b9affe96ea2dd 100644
--- a/src/plugins/data/server/search/index.ts
+++ b/src/plugins/data/server/search/index.ts
@@ -13,3 +13,4 @@ export * from './strategies/eql_search';
export { usageProvider, SearchUsage, searchUsageObserver } from './collectors';
export * from './aggs';
export * from './session';
+export * from './errors/no_search_id_in_session';
diff --git a/src/plugins/data/server/search/search_service.test.ts b/src/plugins/data/server/search/search_service.test.ts
index 52ee8e60a5b26..314cb2c3acbf8 100644
--- a/src/plugins/data/server/search/search_service.test.ts
+++ b/src/plugins/data/server/search/search_service.test.ts
@@ -25,6 +25,7 @@ import {
ISearchSessionService,
ISearchStart,
ISearchStrategy,
+ NoSearchIdInSessionError,
} from '.';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { expressionsPluginMock } from '../../../expressions/public/mocks';
@@ -175,6 +176,22 @@ describe('Search service', () => {
expect(request).toStrictEqual({ ...searchRequest, id: 'my_id' });
});
+ it('searches even if id is not found in session during restore', async () => {
+ const searchRequest = { params: {} };
+ const options = { sessionId, isStored: true, isRestore: true };
+
+ mockSessionClient.getId = jest.fn().mockImplementation(() => {
+ throw new NoSearchIdInSessionError();
+ });
+
+ const res = await mockScopedClient.search(searchRequest, options).toPromise();
+
+ const [request, callOptions] = mockStrategy.search.mock.calls[0];
+ expect(callOptions).toBe(options);
+ expect(request).toStrictEqual({ ...searchRequest });
+ expect(res.isRestored).toBe(false);
+ });
+
it('does not fail if `trackId` throws', async () => {
const searchRequest = { params: {} };
const options = { sessionId, isStored: false, isRestore: false };
diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts
index a651d7b3bf105..00dffefa5e3a6 100644
--- a/src/plugins/data/server/search/search_service.ts
+++ b/src/plugins/data/server/search/search_service.ts
@@ -19,7 +19,7 @@ import {
SharedGlobalConfig,
StartServicesAccessor,
} from 'src/core/server';
-import { first, switchMap, tap } from 'rxjs/operators';
+import { first, map, switchMap, tap, withLatestFrom } from 'rxjs/operators';
import { BfetchServerSetup } from 'src/plugins/bfetch/server';
import { ExpressionsServerSetup } from 'src/plugins/expressions/server';
import type {
@@ -80,6 +80,7 @@ import { registerBsearchRoute } from './routes/bsearch';
import { getKibanaContext } from './expressions/kibana_context';
import { enhancedEsSearchStrategyProvider } from './strategies/ese_search';
import { eqlSearchStrategyProvider } from './strategies/eql_search';
+import { NoSearchIdInSessionError } from './errors/no_search_id_in_session';
type StrategyMap = Record>;
@@ -287,24 +288,48 @@ export class SearchService implements Plugin {
options.strategy
);
- const getSearchRequest = async () =>
- !options.sessionId || !options.isRestore || request.id
- ? request
- : {
+ const getSearchRequest = async () => {
+ if (!options.sessionId || !options.isRestore || request.id) {
+ return request;
+ } else {
+ try {
+ const id = await deps.searchSessionsClient.getId(request, options);
+ this.logger.debug(`Found search session id for request ${id}`);
+ return {
...request,
- id: await deps.searchSessionsClient.getId(request, options),
+ id,
};
+ } catch (e) {
+ if (e instanceof NoSearchIdInSessionError) {
+ this.logger.debug('Ignoring missing search ID');
+ return request;
+ } else {
+ throw e;
+ }
+ }
+ }
+ };
- return from(getSearchRequest()).pipe(
+ const searchRequest$ = from(getSearchRequest());
+ const search$ = searchRequest$.pipe(
switchMap((searchRequest) => strategy.search(searchRequest, options, deps)),
- tap((response) => {
- if (!options.sessionId || !response.id || options.isRestore) return;
+ withLatestFrom(searchRequest$),
+ tap(([response, requestWithId]) => {
+ if (!options.sessionId || !response.id || (options.isRestore && requestWithId.id)) return;
// intentionally swallow tracking error, as it shouldn't fail the search
deps.searchSessionsClient.trackId(request, response.id, options).catch((trackErr) => {
this.logger.error(trackErr);
});
+ }),
+ map(([response, requestWithId]) => {
+ return {
+ ...response,
+ isRestored: !!requestWithId.id,
+ };
})
);
+
+ return search$;
} catch (e) {
return throwError(e);
}
diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md
index f0466dd317ab7..44be1a2255433 100644
--- a/src/plugins/data/server/server.api.md
+++ b/src/plugins/data/server/server.api.md
@@ -1211,6 +1211,14 @@ export enum METRIC_TYPES {
TOP_HITS = "top_hits"
}
+// Warning: (ae-forgotten-export) The symbol "KbnError" needs to be exported by the entry point index.d.ts
+// Warning: (ae-missing-release-tag) "NoSearchIdInSessionError" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export class NoSearchIdInSessionError extends KbnError {
+ constructor();
+}
+
// Warning: (ae-missing-release-tag) "OptionedParamType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -1543,18 +1551,18 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
// src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "HistogramFormat" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:128:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:128:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:244:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:244:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:256:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:257:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:258:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:262:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:263:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:267:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:270:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
-// src/plugins/data/server/index.ts:271:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:245:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:245:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:257:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:258:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:259:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:263:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:264:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:268:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:271:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/server/index.ts:272:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/plugin.ts:81:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:115:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/status.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/status.test.tsx
index 86f5564a17d52..59da0f0f4d17e 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/status.test.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/status.test.tsx
@@ -27,6 +27,7 @@ describe('Background Search Session management status labels', () => {
id: 'wtywp9u2802hahgp-gsla',
restoreUrl: '/app/great-app-url/#45',
reloadUrl: '/app/great-app-url/#45',
+ numSearches: 1,
appId: 'security',
status: SearchSessionStatus.IN_PROGRESS,
created: '2020-12-02T00:19:32Z',
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx
index 42ff270ed44a0..6dfe3a5153670 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/components/table/table.test.tsx
@@ -70,6 +70,7 @@ describe('Background Search Session Management Table', () => {
status: SearchSessionStatus.IN_PROGRESS,
created: '2020-12-02T00:19:32Z',
expires: '2020-12-07T00:19:32Z',
+ idMapping: {},
},
},
],
@@ -95,10 +96,12 @@ describe('Background Search Session Management Table', () => {
);
});
- expect(table.find('thead th').map((node) => node.text())).toMatchInlineSnapshot(`
+ expect(table.find('thead th .euiTableCellContent__text').map((node) => node.text()))
+ .toMatchInlineSnapshot(`
Array [
"App",
"Name",
+ "# Searches",
"Status",
"Created",
"Expiration",
@@ -130,6 +133,7 @@ describe('Background Search Session Management Table', () => {
Array [
"App",
"Namevery background search ",
+ "# Searches0",
"StatusExpired",
"Created2 Dec, 2020, 00:19:32",
"Expiration--",
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts
index 3857b08ad0a3a..cc79f8002a98c 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.test.ts
@@ -52,6 +52,7 @@ describe('Search Sessions Management API', () => {
status: 'complete',
initialState: {},
restoreState: {},
+ idMapping: [],
},
},
],
@@ -78,6 +79,7 @@ describe('Search Sessions Management API', () => {
"id": "hello-pizza-123",
"initialState": Object {},
"name": "Veggie",
+ "numSearches": 0,
"reloadUrl": "hello-cool-undefined-url",
"restoreState": Object {},
"restoreUrl": "hello-cool-undefined-url",
@@ -100,6 +102,7 @@ describe('Search Sessions Management API', () => {
expires: moment().subtract(3, 'days'),
initialState: {},
restoreState: {},
+ idMapping: {},
},
},
],
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts
index 3710dfa16e76b..0369dc4a839b5 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/api.ts
@@ -90,6 +90,7 @@ const mapToUISession = (urls: UrlGeneratorsStart, config: SessionsConfigSchema)
urlGeneratorId,
initialState,
restoreState,
+ idMapping,
} = savedObject.attributes;
const status = getUIStatus(savedObject.attributes);
@@ -113,6 +114,7 @@ const mapToUISession = (urls: UrlGeneratorsStart, config: SessionsConfigSchema)
reloadUrl,
initialState,
restoreState,
+ numSearches: Object.keys(idMapping).length,
};
};
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx
index 4b68e0c9e2afd..fc4e67360ea4a 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.test.tsx
@@ -70,6 +70,7 @@ describe('Search Sessions Management table column factory', () => {
reloadUrl: '/app/great-app-url',
restoreUrl: '/app/great-app-url/#42',
appId: 'discovery',
+ numSearches: 3,
status: SearchSessionStatus.IN_PROGRESS,
created: '2020-12-02T00:19:32Z',
expires: '2020-12-07T00:19:32Z',
@@ -95,6 +96,12 @@ describe('Search Sessions Management table column factory', () => {
"sortable": true,
"width": "20%",
},
+ Object {
+ "field": "numSearches",
+ "name": "# Searches",
+ "render": [Function],
+ "sortable": true,
+ },
Object {
"field": "status",
"name": "Status",
@@ -146,10 +153,29 @@ describe('Search Sessions Management table column factory', () => {
});
});
+ // Num of searches column
+ describe('num of searches', () => {
+ test('renders', () => {
+ const [, , numOfSearches] = getColumns(
+ mockCoreStart,
+ mockPluginsSetup,
+ api,
+ mockConfig,
+ tz,
+ handleAction
+ ) as Array>;
+
+ const numOfSearchesLine = mount(
+ numOfSearches.render!(mockSession.numSearches, mockSession) as ReactElement
+ );
+ expect(numOfSearchesLine.text()).toMatchInlineSnapshot(`"3"`);
+ });
+ });
+
// Status column
describe('status', () => {
test('render in_progress', () => {
- const [, , status] = getColumns(
+ const [, , , status] = getColumns(
mockCoreStart,
mockPluginsSetup,
api,
@@ -165,7 +191,7 @@ describe('Search Sessions Management table column factory', () => {
});
test('error handling', () => {
- const [, , status] = getColumns(
+ const [, , , status] = getColumns(
mockCoreStart,
mockPluginsSetup,
api,
@@ -188,7 +214,7 @@ describe('Search Sessions Management table column factory', () => {
test('render using Browser timezone', () => {
tz = 'Browser';
- const [, , , createdDateCol] = getColumns(
+ const [, , , , createdDateCol] = getColumns(
mockCoreStart,
mockPluginsSetup,
api,
@@ -205,7 +231,7 @@ describe('Search Sessions Management table column factory', () => {
test('render using AK timezone', () => {
tz = 'US/Alaska';
- const [, , , createdDateCol] = getColumns(
+ const [, , , , createdDateCol] = getColumns(
mockCoreStart,
mockPluginsSetup,
api,
@@ -220,7 +246,7 @@ describe('Search Sessions Management table column factory', () => {
});
test('error handling', () => {
- const [, , , createdDateCol] = getColumns(
+ const [, , , , createdDateCol] = getColumns(
mockCoreStart,
mockPluginsSetup,
api,
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx
index 1805ef52b85f1..d8d2fa0aeac59 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/lib/get_columns.tsx
@@ -120,6 +120,20 @@ export const getColumns = (
},
},
+ // # Searches
+ {
+ field: 'numSearches',
+ name: i18n.translate('xpack.data.mgmt.searchSessions.table.numSearches', {
+ defaultMessage: '# Searches',
+ }),
+ sortable: true,
+ render: (numSearches: UISession['numSearches'], session) => (
+
+ {numSearches}
+
+ ),
+ },
+
// Session status
{
field: 'status',
diff --git a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/types.ts b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/types.ts
index d0d5ee9fb17dd..6a8ace8dbdc79 100644
--- a/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/types.ts
+++ b/x-pack/plugins/data_enhanced/public/search/sessions_mgmt/types.ts
@@ -34,6 +34,7 @@ export interface UISession {
created: string;
expires: string | null;
status: UISearchSessionState;
+ numSearches: number;
actions?: ACTION[];
reloadUrl: string;
restoreUrl: string;
diff --git a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts
index 138f42549a094..81a12f607935d 100644
--- a/x-pack/plugins/data_enhanced/server/search/session/session_service.ts
+++ b/x-pack/plugins/data_enhanced/server/search/session/session_service.ts
@@ -24,7 +24,11 @@ import {
ENHANCED_ES_SEARCH_STRATEGY,
SEARCH_SESSION_TYPE,
} from '../../../../../../src/plugins/data/common';
-import { esKuery, ISearchSessionService } from '../../../../../../src/plugins/data/server';
+import {
+ esKuery,
+ ISearchSessionService,
+ NoSearchIdInSessionError,
+} from '../../../../../../src/plugins/data/server';
import { AuthenticatedUser, SecurityPluginSetup } from '../../../../security/server';
import {
TaskManagerSetupContract,
@@ -436,7 +440,7 @@ export class SearchSessionService
const requestHash = createRequestHash(searchRequest.params);
if (!session.attributes.idMapping.hasOwnProperty(requestHash)) {
this.logger.error(`getId | ${sessionId} | ${requestHash} not found`);
- throw new Error('No search ID in this session matching the given search request');
+ throw new NoSearchIdInSessionError();
}
this.logger.debug(`getId | ${sessionId} | ${requestHash}`);
diff --git a/x-pack/test/api_integration/apis/search/session.ts b/x-pack/test/api_integration/apis/search/session.ts
index d47199a0f1c1e..06be7c6759bc0 100644
--- a/x-pack/test/api_integration/apis/search/session.ts
+++ b/x-pack/test/api_integration/apis/search/session.ts
@@ -403,7 +403,12 @@ export default function ({ getService }: FtrProviderContext) {
const { id: id1 } = searchRes1.body;
// it might take the session a moment to be created
- await new Promise((resolve) => setTimeout(resolve, 2500));
+ await retry.waitFor('search session created', async () => {
+ const response = await supertest
+ .get(`/internal/session/${sessionId}`)
+ .set('kbn-xsrf', 'foo');
+ return response.body.statusCode === undefined;
+ });
const getSessionFirstTime = await supertest
.get(`/internal/session/${sessionId}`)