Skip to content

Commit

Permalink
[Search][Discover] Restore searchSessionId from URL (#81633) (#83162)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dosant committed Nov 11, 2020
1 parent ff48a84 commit b16bb24
Show file tree
Hide file tree
Showing 7 changed files with 378 additions and 5 deletions.
30 changes: 25 additions & 5 deletions src/plugins/discover/public/application/angular/discover.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import {
MODIFY_COLUMNS_ON_SWITCH,
} from '../../../common';
import { METRIC_TYPE } from '@kbn/analytics';
import { SEARCH_SESSION_ID_QUERY_PARAM } from '../../url_generator';
import { removeQueryParam, getQueryParams } from '../../../../kibana_utils/public';

const fetchStatuses = {
UNINITIALIZED: 'uninitialized',
Expand All @@ -91,6 +93,9 @@ const fetchStatuses = {
ERROR: 'error',
};

const getSearchSessionIdFromURL = (history) =>
getQueryParams(history.location)[SEARCH_SESSION_ID_QUERY_PARAM];

const app = getAngularModule();

app.config(($routeProvider) => {
Expand Down Expand Up @@ -208,6 +213,8 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
};

const history = getHistory();
// used for restoring background session
let isInitialSearch = true;

const {
appStateContainer,
Expand Down Expand Up @@ -798,17 +805,30 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
if (abortController) abortController.abort();
abortController = new AbortController();

const sessionId = data.search.session.start();
const searchSessionId = (() => {
const searchSessionIdFromURL = getSearchSessionIdFromURL(history);
if (searchSessionIdFromURL) {
if (isInitialSearch) {
data.search.session.restore(searchSessionIdFromURL);
isInitialSearch = false;
return searchSessionIdFromURL;
} else {
// navigating away from background search
removeQueryParam(history, SEARCH_SESSION_ID_QUERY_PARAM);
}
}
return data.search.session.start();
})();

$scope
.updateDataSource()
.then(setupVisualization)
.then(function () {
$scope.fetchStatus = fetchStatuses.LOADING;
logInspectorRequest();
logInspectorRequest({ searchSessionId });
return $scope.searchSource.fetch({
abortSignal: abortController.signal,
sessionId,
sessionId: searchSessionId,
});
})
.then(onResults)
Expand Down Expand Up @@ -900,15 +920,15 @@ function discoverController($element, $route, $scope, $timeout, $window, Promise
$scope.fetchStatus = fetchStatuses.COMPLETE;
}

function logInspectorRequest() {
function logInspectorRequest({ searchSessionId = null } = { searchSessionId: null }) {
inspectorAdapters.requests.reset();
const title = i18n.translate('discover.inspectorRequestDataTitle', {
defaultMessage: 'data',
});
const description = i18n.translate('discover.inspectorRequestDescription', {
defaultMessage: 'This request queries Elasticsearch to fetch the data for the search.',
});
inspectorRequest = inspectorAdapters.requests.start(title, { description });
inspectorRequest = inspectorAdapters.requests.start(title, { description, searchSessionId });
inspectorRequest.stats(getRequestInspectorStats($scope.searchSource));
$scope.searchSource.getSearchRequestBody().then((body) => {
inspectorRequest.json(body);
Expand Down
9 changes: 9 additions & 0 deletions src/plugins/discover/public/url_generator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ describe('Discover url generator', () => {
});
});

test('can specify a search session id', async () => {
const { generator } = await setup();
const url = await generator.createUrl({
searchSessionId: '__test__',
});
expect(url).toMatchInlineSnapshot(`"xyz/app/discover#/?_g=()&_a=()&searchSessionId=__test__"`);
expect(url).toContain('__test__');
});

describe('useHash property', () => {
describe('when default useHash is set to false', () => {
test('when using default, sets index pattern ID in the generated URL', async () => {
Expand Down
12 changes: 12 additions & 0 deletions src/plugins/discover/public/url_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,20 @@ export interface DiscoverUrlGeneratorState {
* whether to hash the data in the url to avoid url length issues.
*/
useHash?: boolean;

/**
* Background search session id
*/
searchSessionId?: string;
}

interface Params {
appBasePath: string;
useHash: boolean;
}

export const SEARCH_SESSION_ID_QUERY_PARAM = 'searchSessionId';

export class DiscoverUrlGenerator
implements UrlGeneratorsDefinition<typeof DISCOVER_APP_URL_GENERATOR> {
constructor(private readonly params: Params) {}
Expand All @@ -88,6 +95,7 @@ export class DiscoverUrlGenerator
savedSearchId,
timeRange,
useHash = this.params.useHash,
searchSessionId,
}: DiscoverUrlGeneratorState): Promise<string> => {
const savedSearchPath = savedSearchId ? encodeURIComponent(savedSearchId) : '';
const appState: {
Expand All @@ -111,6 +119,10 @@ export class DiscoverUrlGenerator
url = setStateToKbnUrl<QueryState>('_g', queryState, { useHash }, url);
url = setStateToKbnUrl('_a', appState, { useHash }, url);

if (searchSessionId) {
url = `${url}&${SEARCH_SESSION_ID_QUERY_PARAM}=${searchSessionId}`;
}

return url;
};
}
58 changes: 58 additions & 0 deletions x-pack/test/functional/apps/discover/async_search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getPageObjects, getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const queryBar = getService('queryBar');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const inspector = getService('inspector');
const PageObjects = getPageObjects(['discover', 'common', 'timePicker', 'header']);

describe('discover async search', () => {
before(async () => {
await esArchiver.loadIfNeeded('logstash_functional');
await esArchiver.load('discover/default');
await PageObjects.common.navigateToApp('discover');
await PageObjects.timePicker.setDefaultAbsoluteRange();
await PageObjects.header.waitUntilLoadingHasFinished();
});

it('search session id should change between searches', async () => {
const searchSessionId1 = await getSearchSessionId();
expect(searchSessionId1).not.to.be.empty();
await queryBar.clickQuerySubmitButton();
const searchSessionId2 = await getSearchSessionId();
expect(searchSessionId2).not.to.be(searchSessionId1);
});

// NOTE: this test will be revised when
// `searchSessionId` functionality actually works
it('search session id should be picked up from the URL', async () => {
const url = await browser.getCurrentUrl();
const fakeSearchSessionId = '__test__';
const savedSessionURL = url + `&searchSessionId=${fakeSearchSessionId}`;
await browser.navigateTo(savedSessionURL);
await PageObjects.header.waitUntilLoadingHasFinished();
const searchSessionId1 = await getSearchSessionId();
expect(searchSessionId1).to.be(fakeSearchSessionId);
await queryBar.clickQuerySubmitButton();
const searchSessionId2 = await getSearchSessionId();
expect(searchSessionId2).not.to.be(searchSessionId1);
});
});

async function getSearchSessionId(): Promise<string> {
await inspector.open();
const searchSessionId = await (
await testSubjects.find('inspectorRequestSearchSessionId')
).getAttribute('data-search-session-id');
await inspector.close();
return searchSessionId;
}
}
1 change: 1 addition & 0 deletions x-pack/test/functional/apps/discover/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./error_handling'));
loadTestFile(require.resolve('./visualize_field'));
loadTestFile(require.resolve('./value_suggestions'));
loadTestFile(require.resolve('./async_search'));
});
}
Binary file not shown.
Loading

0 comments on commit b16bb24

Please sign in to comment.