Skip to content

Commit

Permalink
use client side param to avoid tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
Dosant committed Jun 23, 2022
1 parent af21b68 commit 5e9d723
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 54 deletions.
13 changes: 12 additions & 1 deletion src/plugins/data/common/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ export interface ISearchOptions {
*/
isStored?: boolean;

/**
* Whether the search was successfully polled after session was saved. Search was added to a session saved object and keepAlive extended.
*/
isSearchStored?: boolean;

/**
* Whether the session is restored (i.e. search requests should re-use the stored search IDs,
* rather than starting from scratch)
Expand All @@ -155,5 +160,11 @@ export interface ISearchOptions {
*/
export type ISearchOptionsSerializable = Pick<
ISearchOptions,
'strategy' | 'legacyHitsTotal' | 'sessionId' | 'isStored' | 'isRestore' | 'executionContext'
| 'strategy'
| 'legacyHitsTotal'
| 'sessionId'
| 'isStored'
| 'isSearchStored'
| 'isRestore'
| 'executionContext'
>;
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ export class SearchInterceptor {
serializableOptions.legacyHitsTotal = combined.legacyHitsTotal;
if (combined.strategy !== undefined) serializableOptions.strategy = combined.strategy;
if (combined.isStored !== undefined) serializableOptions.isStored = combined.isStored;
if (combined.isSearchStored !== undefined)
serializableOptions.isSearchStored = combined.isSearchStored;
if (combined.executionContext !== undefined) {
serializableOptions.executionContext = combined.executionContext;
}
Expand All @@ -229,15 +231,27 @@ export class SearchInterceptor {
const { sessionId, strategy } = options;

const search = () => {
searchTracker?.polled();
const [{ isSearchStored }, afterPoll] = searchTracker?.beforePoll() ?? [
{ isSearchStored: false },
({ isSearchStored: boolean }) => {},
];
return this.runSearch(
{ id, ...request },
{
...options,
...this.deps.session.getSearchOptions(sessionId),
abortSignal: searchAbortController.getSignal(),
isSearchStored,
}
);
)
.then((result) => {
afterPoll({ isSearchStored: result.isStored ?? false });
return result;
})
.catch((err) => {
afterPoll({ isSearchStored: false });
throw err;
});
};

const searchTracker = this.deps.session.isCurrentSession(sessionId)
Expand Down
21 changes: 17 additions & 4 deletions src/plugins/data/public/search/session/session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,13 @@ interface TrackSearchHandler {
error(): void;

/**
* Call to notify when search was polled
* Call to notify when search is about to be polled
* Returns a tuple with a current tracked search state and a callback to "confirm" when polling was completed and if search was successfully extended
*/
polled(): void;
beforePoll(): [
currentSearchState: { isSearchStored: boolean },
afterPoll: (newSearchState: { isSearchStored: boolean }) => void
];
}

/**
Expand Down Expand Up @@ -331,11 +335,20 @@ export class SessionService {
error: () => {
this.state.transitions.errorSearch(searchDescriptor);
},
polled: () => {
beforePoll: () => {
const search = this.state.selectors.getSearch(searchDescriptor);
this.state.transitions.updateSearchMeta(searchDescriptor, {
lastPollingTime: new Date(),
isStored: this.isStored(),
});

return [
{ isSearchStored: search?.searchMeta?.isStored ?? false },
({ isSearchStored }) => {
this.state.transitions.updateSearchMeta(searchDescriptor, {
isStored: isSearchStored,
});
},
];
},
};
}
Expand Down
31 changes: 21 additions & 10 deletions src/plugins/data/server/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,18 +392,29 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
!(options.isRestore && searchRequest.id) // and not restoring already tracked search
) {
// then track this search inside the search-session saved object
return from(deps.searchSessionsClient.trackId(request, response.id, options)).pipe(
map(() => ({

// check if search was already tracked and extended, don't track again in this case
if (options.isSearchStored) {
return of({
...response,
isStored: true,
})),
catchError((e) => {
this.logger.error(
`Error while trying to track search id: ${e?.message}. This might lead to untracked long-running search.`
);
return of(response);
})
);
});
} else {
return from(
deps.searchSessionsClient.trackId(request, response.id, options)
).pipe(
map(() => ({
...response,
isStored: true,
})),
catchError((e) => {
this.logger.error(
`Error while trying to track search id: ${e?.message}. This might lead to untracked long-running search.`
);
return of(response);
})
);
}
} else {
return of(response);
}
Expand Down
37 changes: 0 additions & 37 deletions src/plugins/data/server/search/session/session_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,19 +392,6 @@ export class SearchSessionService
if (!this.sessionConfig.enabled || !sessionId || !searchId) return;
this.logger.debug(`trackId | ${sessionId} | ${searchId}`);

let isIdTracked = false;
try {
const hasId = await this.checkId(deps, user, searchRequest, options);
isIdTracked = hasId;
} catch (e) {
this.logger.warn(
`trackId | Error while checking if search is already tracked by a session object: "${e?.message}". Continue assuming not tracked.`
);
}

// no need to update search saved object if id is already tracked in a session object
if (isIdTracked) return;

let idMapping: Record<string, SearchSessionRequestInfo> = {};

if (searchRequest.params) {
Expand Down Expand Up @@ -465,30 +452,6 @@ export class SearchSessionService
return session.attributes.idMapping[requestHash].id;
};

/**
* Look up an existing search ID that matches the given request in the given session
* @internal
*/
public checkId = async (
deps: SearchSessionDependencies,
user: AuthenticatedUser | null,
searchRequest: IKibanaSearchRequest,
{ sessionId, isStored }: ISearchOptions
): Promise<boolean> => {
if (!this.sessionConfig.enabled) {
throw new Error('Search sessions are disabled');
} else if (!sessionId) {
throw new Error('Session ID is required');
} else if (!isStored) {
throw new Error('Cannot check search ID from a session that is not stored');
}

const session = await this.get(deps, user, sessionId);
const requestHash = createRequestHash(searchRequest.params);

return session.attributes.idMapping.hasOwnProperty(requestHash);
};

public asScopedProvider = ({ savedObjects, elasticsearch }: CoreStart) => {
return (request: KibanaRequest) => {
const user = this.security?.authc.getCurrentUser(request) ?? null;
Expand Down

0 comments on commit 5e9d723

Please sign in to comment.