diff --git a/src/platform/plugins/shared/data/server/search/session/get_session_status.test.ts b/src/platform/plugins/shared/data/server/search/session/get_session_status.test.ts index cd45066a1c8e3..aea9fe0acc977 100644 --- a/src/platform/plugins/shared/data/server/search/session/get_session_status.test.ts +++ b/src/platform/plugins/shared/data/server/search/session/get_session_status.test.ts @@ -13,6 +13,7 @@ import type { SearchSessionSavedObjectAttributes } from '../../../common'; import { SearchSessionStatus } from '../../../common'; import moment from 'moment'; import type { SearchSessionsConfigSchema } from '../../config'; +import { createSearchSessionSavedObjectAttributesMock } from './mocks'; const mockInProgressSearchResponse = { body: { @@ -46,13 +47,30 @@ describe('getSessionStatus', () => { const deps = { esClient: elasticsearchServiceMock.createElasticsearchClient(), }; - test("returns an in_progress status if there's nothing inside the session", async () => { - const session: any = { - idMapping: {}, - touched: moment(), - }; - expect(await getSessionStatus(deps, session, mockConfig)).toEqual({ - status: SearchSessionStatus.IN_PROGRESS, + + describe('when there are no searches inside the session', () => { + describe('when the search is brand new', () => { + test('returns an in_progress status', async () => { + const session = createSearchSessionSavedObjectAttributesMock({ + idMapping: {}, + created: moment().toISOString(), + }); + expect(await getSessionStatus(deps, session, mockConfig)).toEqual({ + status: SearchSessionStatus.IN_PROGRESS, + }); + }); + }); + + describe('when the search is has been created for a few seconds', () => { + test('returns an error status', async () => { + const session = createSearchSessionSavedObjectAttributesMock({ + idMapping: {}, + created: moment().subtract(1, 'minutes').toISOString(), + }); + expect(await getSessionStatus(deps, session, mockConfig)).toEqual({ + status: SearchSessionStatus.ERROR, + }); + }); }); }); diff --git a/src/platform/plugins/shared/data/server/search/session/get_session_status.ts b/src/platform/plugins/shared/data/server/search/session/get_session_status.ts index 530a65c2906d1..f1286c948ba58 100644 --- a/src/platform/plugins/shared/data/server/search/session/get_session_status.ts +++ b/src/platform/plugins/shared/data/server/search/session/get_session_status.ts @@ -15,6 +15,11 @@ import { SearchStatus } from './types'; import type { SearchSessionsConfigSchema } from '../../config'; import { getSearchStatus } from './get_search_status'; +// A session should is considered "new" for the first 30 seconds after creation. We need some arbitrary value here +// because if a sessions stays for too long with no searches assigned to it something happened and we should mark it as error. +// Some examples of possible issues: the browser is closed or in another tab the search requests are canceled. +const NEW_SESSION_THRESHOLD_SECONDS = 30; + export async function getSessionStatus( deps: { esClient: ElasticsearchClient }, session: SearchSessionSavedObjectAttributes, @@ -31,6 +36,13 @@ export async function getSessionStatus( } const searches = Object.values(session.idMapping); + + const secondsSinceCreated = moment().diff(moment(session.created), 'seconds'); + const isOldSession = secondsSinceCreated > NEW_SESSION_THRESHOLD_SECONDS; + if (searches.length === 0 && isOldSession) { + return { status: SearchSessionStatus.ERROR }; + } + const searchStatuses = await Promise.all( searches.map(async (s) => { const status = await getSearchStatus({ diff --git a/src/platform/plugins/shared/data/server/search/session/mocks.ts b/src/platform/plugins/shared/data/server/search/session/mocks.ts index 25a4efaded55d..a30c46302ddf1 100644 --- a/src/platform/plugins/shared/data/server/search/session/mocks.ts +++ b/src/platform/plugins/shared/data/server/search/session/mocks.ts @@ -10,6 +10,7 @@ import moment from 'moment'; import type { IScopedSearchSessionsClient } from './types'; import type { SearchSessionsConfigSchema } from '../../config'; +import type { SearchSessionSavedObjectAttributes } from '../../../common'; export function createSearchSessionsClientMock(): jest.Mocked { return { @@ -33,3 +34,16 @@ export function createSearchSessionsClientMock(): jest.Mocked = {} +) { + return { + sessionId: '1234', + created: moment().toISOString(), + expires: moment().add(7, 'days').toISOString(), + idMapping: {}, + version: '9.2.0', + ...overrides, + } as SearchSessionSavedObjectAttributes; +}