Skip to content

Commit 62d608d

Browse files
[9.2] [Background search] Return error state when there are no searches (#241411) (#241932)
# Backport This will backport the following commits from `main` to `9.2`: - [[Background search] Return error state when there are no searches (#241411)](#241411) <!--- Backport version: 9.6.6 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sorenlouv/backport) <!--BACKPORT [{"author":{"name":"Alejandro García Parrondo","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-11-05T10:10:43Z","message":"[Background search] Return error state when there are no searches (#241411)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/240887\n\nRight now if a background search has 0 searches it stays in the \"In\nprogress\" state but that's not correct. If no searches are added to the\nbackground search it means that something went wrong. With this PR we\nwill label as error the search sessions if they have 0 searches after\nbeing created for 30 seconds.\n\n| Before | After |\n|--------|------|\n| <img width=\"716\" height=\"89\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/1bb4b60a-20d3-488e-b4e9-9fd8cd4d0b24\"\n/> | <img width=\"675\" height=\"88\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/4befb6c0-5edb-4229-9919-e2b76ae90731\"\n/> |\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.","sha":"131f1a002666e1a3065dacc30754a519bce7a2cc","branchLabelMapping":{"^v9.3.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Project:AsyncSearch","Team:DataDiscovery","backport:version","v9.3.0","v9.2.1"],"title":"[Background search] Return error state when there are no searches","number":241411,"url":"https://github.com/elastic/kibana/pull/241411","mergeCommit":{"message":"[Background search] Return error state when there are no searches (#241411)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/240887\n\nRight now if a background search has 0 searches it stays in the \"In\nprogress\" state but that's not correct. If no searches are added to the\nbackground search it means that something went wrong. With this PR we\nwill label as error the search sessions if they have 0 searches after\nbeing created for 30 seconds.\n\n| Before | After |\n|--------|------|\n| <img width=\"716\" height=\"89\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/1bb4b60a-20d3-488e-b4e9-9fd8cd4d0b24\"\n/> | <img width=\"675\" height=\"88\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/4befb6c0-5edb-4229-9919-e2b76ae90731\"\n/> |\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.","sha":"131f1a002666e1a3065dacc30754a519bce7a2cc"}},"sourceBranch":"main","suggestedTargetBranches":["9.2"],"targetPullRequestStates":[{"branch":"main","label":"v9.3.0","branchLabelMappingKey":"^v9.3.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/241411","number":241411,"mergeCommit":{"message":"[Background search] Return error state when there are no searches (#241411)\n\n## Summary\n\nCloses https://github.com/elastic/kibana/issues/240887\n\nRight now if a background search has 0 searches it stays in the \"In\nprogress\" state but that's not correct. If no searches are added to the\nbackground search it means that something went wrong. With this PR we\nwill label as error the search sessions if they have 0 searches after\nbeing created for 30 seconds.\n\n| Before | After |\n|--------|------|\n| <img width=\"716\" height=\"89\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/1bb4b60a-20d3-488e-b4e9-9fd8cd4d0b24\"\n/> | <img width=\"675\" height=\"88\" alt=\"image\"\nsrc=\"https://github.com/user-attachments/assets/4befb6c0-5edb-4229-9919-e2b76ae90731\"\n/> |\n\n\n### Checklist\n\nCheck the PR satisfies following conditions. \n\nReviewers should verify this PR satisfies this list as well.\n\n- [x] [Unit or functional\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\nwere updated or added to match the most common scenarios\n- [x] The PR description includes the appropriate Release Notes section,\nand the correct `release_note:*` label is applied per the\n[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\n- [x] Review the [backport\nguidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)\nand apply applicable `backport:*` labels.","sha":"131f1a002666e1a3065dacc30754a519bce7a2cc"}},{"branch":"9.2","label":"v9.2.1","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Alejandro García Parrondo <[email protected]>
1 parent 4765966 commit 62d608d

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

src/platform/plugins/shared/data/server/search/session/get_session_status.test.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { SearchSessionSavedObjectAttributes } from '../../../common';
1313
import { SearchSessionStatus } from '../../../common';
1414
import moment from 'moment';
1515
import type { SearchSessionsConfigSchema } from '../../config';
16+
import { createSearchSessionSavedObjectAttributesMock } from './mocks';
1617

1718
const mockInProgressSearchResponse = {
1819
body: {
@@ -46,13 +47,30 @@ describe('getSessionStatus', () => {
4647
const deps = {
4748
esClient: elasticsearchServiceMock.createElasticsearchClient(),
4849
};
49-
test("returns an in_progress status if there's nothing inside the session", async () => {
50-
const session: any = {
51-
idMapping: {},
52-
touched: moment(),
53-
};
54-
expect(await getSessionStatus(deps, session, mockConfig)).toEqual({
55-
status: SearchSessionStatus.IN_PROGRESS,
50+
51+
describe('when there are no searches inside the session', () => {
52+
describe('when the search is brand new', () => {
53+
test('returns an in_progress status', async () => {
54+
const session = createSearchSessionSavedObjectAttributesMock({
55+
idMapping: {},
56+
created: moment().toISOString(),
57+
});
58+
expect(await getSessionStatus(deps, session, mockConfig)).toEqual({
59+
status: SearchSessionStatus.IN_PROGRESS,
60+
});
61+
});
62+
});
63+
64+
describe('when the search is has been created for a few seconds', () => {
65+
test('returns an error status', async () => {
66+
const session = createSearchSessionSavedObjectAttributesMock({
67+
idMapping: {},
68+
created: moment().subtract(1, 'minutes').toISOString(),
69+
});
70+
expect(await getSessionStatus(deps, session, mockConfig)).toEqual({
71+
status: SearchSessionStatus.ERROR,
72+
});
73+
});
5674
});
5775
});
5876

src/platform/plugins/shared/data/server/search/session/get_session_status.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ import { SearchStatus } from './types';
1515
import type { SearchSessionsConfigSchema } from '../../config';
1616
import { getSearchStatus } from './get_search_status';
1717

18+
// A session should is considered "new" for the first 30 seconds after creation. We need some arbitrary value here
19+
// because if a sessions stays for too long with no searches assigned to it something happened and we should mark it as error.
20+
// Some examples of possible issues: the browser is closed or in another tab the search requests are canceled.
21+
const NEW_SESSION_THRESHOLD_SECONDS = 30;
22+
1823
export async function getSessionStatus(
1924
deps: { esClient: ElasticsearchClient },
2025
session: SearchSessionSavedObjectAttributes,
@@ -31,6 +36,13 @@ export async function getSessionStatus(
3136
}
3237

3338
const searches = Object.values(session.idMapping);
39+
40+
const secondsSinceCreated = moment().diff(moment(session.created), 'seconds');
41+
const isOldSession = secondsSinceCreated > NEW_SESSION_THRESHOLD_SECONDS;
42+
if (searches.length === 0 && isOldSession) {
43+
return { status: SearchSessionStatus.ERROR };
44+
}
45+
3446
const searchStatuses = await Promise.all(
3547
searches.map(async (s) => {
3648
const status = await getSearchStatus({

src/platform/plugins/shared/data/server/search/session/mocks.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import moment from 'moment';
1111
import type { IScopedSearchSessionsClient } from './types';
1212
import type { SearchSessionsConfigSchema } from '../../config';
13+
import type { SearchSessionSavedObjectAttributes } from '../../../common';
1314

1415
export function createSearchSessionsClientMock(): jest.Mocked<IScopedSearchSessionsClient> {
1516
return {
@@ -33,3 +34,16 @@ export function createSearchSessionsClientMock(): jest.Mocked<IScopedSearchSessi
3334
),
3435
};
3536
}
37+
38+
export function createSearchSessionSavedObjectAttributesMock(
39+
overrides: Partial<SearchSessionSavedObjectAttributes> = {}
40+
) {
41+
return {
42+
sessionId: '1234',
43+
created: moment().toISOString(),
44+
expires: moment().add(7, 'days').toISOString(),
45+
idMapping: {},
46+
version: '9.2.0',
47+
...overrides,
48+
} as SearchSessionSavedObjectAttributes;
49+
}

0 commit comments

Comments
 (0)