[data.search.session] Store search strategy in saved object for background sessions (#86057)

* [data.search.session] Store search strategy in saved object

* Update unit test to check strategy

* Fix test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Lukas Olson 2021-01-04 17:39:57 -07:00 committed by GitHub
parent 52f6c7cf5c
commit 8ac632b068
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 20 deletions

View file

@ -15,4 +15,5 @@ export {
BackgroundSessionSavedObjectAttributes, BackgroundSessionSavedObjectAttributes,
BackgroundSessionFindOptions, BackgroundSessionFindOptions,
BackgroundSessionStatus, BackgroundSessionStatus,
BackgroundSessionSearchInfo,
} from './search'; } from './search';

View file

@ -19,7 +19,12 @@ export interface BackgroundSessionSavedObjectAttributes {
urlGeneratorId: string; urlGeneratorId: string;
initialState: Record<string, unknown>; initialState: Record<string, unknown>;
restoreState: Record<string, unknown>; restoreState: Record<string, unknown>;
idMapping: Record<string, string>; idMapping: Record<string, BackgroundSessionSearchInfo>;
}
export interface BackgroundSessionSearchInfo {
id: string; // ID of the async search request
strategy: string; // Search strategy used to submit the search request
} }
export interface BackgroundSessionFindOptions { export interface BackgroundSessionFindOptions {

View file

@ -30,6 +30,7 @@ describe('BackgroundSessionService', () => {
const MOCK_SESSION_ID = 'session-id-mock'; const MOCK_SESSION_ID = 'session-id-mock';
const MOCK_ASYNC_ID = '123456'; const MOCK_ASYNC_ID = '123456';
const MOCK_STRATEGY = 'ese';
const MOCK_KEY_HASH = '608de49a4600dbb5b173492759792e4a'; const MOCK_KEY_HASH = '608de49a4600dbb5b173492759792e4a';
const createMockInternalSavedObjectClient = ( const createMockInternalSavedObjectClient = (
@ -47,7 +48,10 @@ describe('BackgroundSessionService', () => {
attributes: { attributes: {
sessionId: MOCK_SESSION_ID, sessionId: MOCK_SESSION_ID,
idMapping: { idMapping: {
'another-key': 'another-async-id', 'another-key': {
id: 'another-async-id',
strategy: 'another-strategy',
},
}, },
}, },
id: MOCK_SESSION_ID, id: MOCK_SESSION_ID,
@ -283,7 +287,7 @@ describe('BackgroundSessionService', () => {
await service.trackId( await service.trackId(
searchRequest, searchRequest,
searchId, searchId,
{ sessionId, isStored }, { sessionId, isStored, strategy: MOCK_STRATEGY },
{ savedObjectsClient } { savedObjectsClient }
); );
@ -313,7 +317,8 @@ describe('BackgroundSessionService', () => {
); );
const [setSessionId, setParams] = setSpy.mock.calls[0]; const [setSessionId, setParams] = setSpy.mock.calls[0];
expect(setParams.ids.get(requestHash)).toBe(searchId); expect(setParams.ids.get(requestHash).id).toBe(searchId);
expect(setParams.ids.get(requestHash).strategy).toBe(MOCK_STRATEGY);
expect(setSessionId).toBe(sessionId); expect(setSessionId).toBe(sessionId);
}); });
@ -326,12 +331,17 @@ describe('BackgroundSessionService', () => {
await service.trackId( await service.trackId(
searchRequest, searchRequest,
searchId, searchId,
{ sessionId, isStored }, { sessionId, isStored, strategy: MOCK_STRATEGY },
{ savedObjectsClient } { savedObjectsClient }
); );
expect(savedObjectsClient.update).toHaveBeenCalledWith(BACKGROUND_SESSION_TYPE, sessionId, { expect(savedObjectsClient.update).toHaveBeenCalledWith(BACKGROUND_SESSION_TYPE, sessionId, {
idMapping: { [requestHash]: searchId }, idMapping: {
[requestHash]: {
id: searchId,
strategy: MOCK_STRATEGY,
},
},
}); });
}); });
}); });
@ -380,7 +390,12 @@ describe('BackgroundSessionService', () => {
name: 'my_name', name: 'my_name',
appId: 'my_app_id', appId: 'my_app_id',
urlGeneratorId: 'my_url_generator_id', urlGeneratorId: 'my_url_generator_id',
idMapping: { [requestHash]: searchId }, idMapping: {
[requestHash]: {
id: searchId,
strategy: MOCK_STRATEGY,
},
},
}, },
references: [], references: [],
}; };
@ -419,7 +434,10 @@ describe('BackgroundSessionService', () => {
const findSpy = jest.fn().mockResolvedValue({ saved_objects: [] }); const findSpy = jest.fn().mockResolvedValue({ saved_objects: [] });
createMockInternalSavedObjectClient(findSpy); createMockInternalSavedObjectClient(findSpy);
const mockIdMapping = createMockIdMapping([[MOCK_KEY_HASH, MOCK_ASYNC_ID]], moment()); const mockIdMapping = createMockIdMapping(
[[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]],
moment()
);
Object.defineProperty(service, 'sessionSearchMap', { Object.defineProperty(service, 'sessionSearchMap', {
get: () => mockIdMapping, get: () => mockIdMapping,
@ -438,7 +456,7 @@ describe('BackgroundSessionService', () => {
createMockInternalSavedObjectClient(findSpy); createMockInternalSavedObjectClient(findSpy);
const mockIdMapping = createMockIdMapping( const mockIdMapping = createMockIdMapping(
[[MOCK_KEY_HASH, MOCK_ASYNC_ID]], [[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]],
moment().subtract(2, 'm') moment().subtract(2, 'm')
); );
@ -459,7 +477,7 @@ describe('BackgroundSessionService', () => {
createMockInternalSavedObjectClient(findSpy); createMockInternalSavedObjectClient(findSpy);
const mockIdMapping = createMockIdMapping( const mockIdMapping = createMockIdMapping(
[[MOCK_KEY_HASH, MOCK_ASYNC_ID]], [[MOCK_KEY_HASH, { id: MOCK_ASYNC_ID, strategy: MOCK_STRATEGY }]],
moment(), moment(),
MAX_UPDATE_RETRIES MAX_UPDATE_RETRIES
); );
@ -528,7 +546,10 @@ describe('BackgroundSessionService', () => {
attributes: { attributes: {
idMapping: { idMapping: {
b: 'c', b: 'c',
[MOCK_KEY_HASH]: MOCK_ASYNC_ID, [MOCK_KEY_HASH]: {
id: MOCK_ASYNC_ID,
strategy: MOCK_STRATEGY,
},
}, },
}, },
}, },
@ -566,7 +587,10 @@ describe('BackgroundSessionService', () => {
id: MOCK_SESSION_ID, id: MOCK_SESSION_ID,
attributes: { attributes: {
idMapping: { idMapping: {
b: 'c', b: {
id: 'c',
strategy: MOCK_STRATEGY,
},
}, },
}, },
}, },

View file

@ -32,6 +32,7 @@ import {
import { import {
BackgroundSessionSavedObjectAttributes, BackgroundSessionSavedObjectAttributes,
BackgroundSessionFindOptions, BackgroundSessionFindOptions,
BackgroundSessionSearchInfo,
BackgroundSessionStatus, BackgroundSessionStatus,
} from '../../../common'; } from '../../../common';
import { BACKGROUND_SESSION_TYPE } from '../../saved_objects'; import { BACKGROUND_SESSION_TYPE } from '../../saved_objects';
@ -51,7 +52,7 @@ export interface BackgroundSessionDependencies {
export interface SessionInfo { export interface SessionInfo {
insertTime: Moment; insertTime: Moment;
retryCount: number; retryCount: number;
ids: Map<string, string>; ids: Map<string, BackgroundSessionSearchInfo>;
} }
export class BackgroundSessionService implements ISessionService { export class BackgroundSessionService implements ISessionService {
@ -316,25 +317,31 @@ export class BackgroundSessionService implements ISessionService {
public trackId = async ( public trackId = async (
searchRequest: IKibanaSearchRequest, searchRequest: IKibanaSearchRequest,
searchId: string, searchId: string,
{ sessionId, isStored }: ISearchOptions, { sessionId, isStored, strategy }: ISearchOptions,
deps: BackgroundSessionDependencies deps: BackgroundSessionDependencies
) => { ) => {
if (!sessionId || !searchId) return; if (!sessionId || !searchId) return;
this.logger.debug(`trackId | ${sessionId} | ${searchId}`); this.logger.debug(`trackId | ${sessionId} | ${searchId}`);
const requestHash = createRequestHash(searchRequest.params); const requestHash = createRequestHash(searchRequest.params);
const searchInfo = {
id: searchId,
strategy: strategy!,
};
// If there is already a saved object for this session, update it to include this request/ID. // If there is already a saved object for this session, update it to include this request/ID.
// Otherwise, just update the in-memory mapping for this session for when the session is saved. // Otherwise, just update the in-memory mapping for this session for when the session is saved.
if (isStored) { if (isStored) {
const attributes = { idMapping: { [requestHash]: searchId } }; const attributes = {
idMapping: { [requestHash]: searchInfo },
};
await this.update(sessionId, attributes, deps); await this.update(sessionId, attributes, deps);
} else { } else {
const map = this.sessionSearchMap.get(sessionId) ?? { const map = this.sessionSearchMap.get(sessionId) ?? {
insertTime: moment(), insertTime: moment(),
retryCount: 0, retryCount: 0,
ids: new Map<string, string>(), ids: new Map<string, BackgroundSessionSearchInfo>(),
}; };
map.ids.set(requestHash, searchId); map.ids.set(requestHash, searchInfo);
this.sessionSearchMap.set(sessionId, map); this.sessionSearchMap.set(sessionId, map);
} }
}; };
@ -363,7 +370,7 @@ export class BackgroundSessionService implements ISessionService {
throw new Error('No search ID in this session matching the given search request'); throw new Error('No search ID in this session matching the given search request');
} }
return session.attributes.idMapping[requestHash]; return session.attributes.idMapping[requestHash].id;
}; };
public asScopedProvider = ({ savedObjects }: CoreStart) => { public asScopedProvider = ({ savedObjects }: CoreStart) => {

View file

@ -119,8 +119,9 @@ export default function ({ getService }: FtrProviderContext) {
const { idMapping } = resp.body.attributes; const { idMapping } = resp.body.attributes;
expect(Object.values(idMapping)).to.contain(id1); const idMappings = Object.values(idMapping).map((value: any) => value.id);
expect(Object.values(idMapping)).to.contain(id2); expect(idMappings).to.contain(id1);
expect(idMappings).to.contain(id2);
}); });
}); });
}); });