From 33efd47ee6927b54b328e901fe31d31eae875325 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 3 May 2023 17:50:08 -0400 Subject: [PATCH] [8.8] [Enterprise Search] Search Apps. - fetch indices one-by-one (#156571) (#156624) # Backport This will backport the following commits from `main` to `8.8`: - [[Enterprise Search] Search Apps. - fetch indices one-by-one (#156571)](https://github.com/elastic/kibana/pull/156571) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Sloane Perrault --- .../enterprise_search/common/types/engines.ts | 2 +- .../server/lib/engines/available_indices.ts | 20 ++++++++++++++++ .../lib/engines/fetch_indices_stats.test.ts | 11 ++++----- .../server/lib/engines/fetch_indices_stats.ts | 24 ++++++++++--------- .../lib/engines/field_capabilities.test.ts | 2 ++ .../server/lib/engines/field_capabilities.ts | 6 +++-- 6 files changed, 44 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/server/lib/engines/available_indices.ts diff --git a/x-pack/plugins/enterprise_search/common/types/engines.ts b/x-pack/plugins/enterprise_search/common/types/engines.ts index d668e729a67ec..c7ec8db1a7cee 100644 --- a/x-pack/plugins/enterprise_search/common/types/engines.ts +++ b/x-pack/plugins/enterprise_search/common/types/engines.ts @@ -26,7 +26,7 @@ export interface EnterpriseSearchEngineDetails { } export interface EnterpriseSearchEngineIndex { - count: number; + count: number | null; health: HealthStatus | 'unknown'; name: string; } diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/available_indices.ts b/x-pack/plugins/enterprise_search/server/lib/engines/available_indices.ts new file mode 100644 index 0000000000000..0f5e9f346769b --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/engines/available_indices.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; + +export const availableIndices = async ( + client: IScopedClusterClient, + indices: string[] +): Promise => { + if (await client.asCurrentUser.indices.exists({ index: indices })) return indices; + + const indicesAndExists: Array<[string, boolean]> = await Promise.all( + indices.map(async (index) => [index, await client.asCurrentUser.indices.exists({ index })]) + ); + return indicesAndExists.flatMap(([index, exists]) => (exists ? [index] : [])); +}; diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.test.ts b/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.test.ts index 55905e40c6835..bb63e51483fe9 100644 --- a/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.test.ts @@ -12,13 +12,14 @@ describe('fetchIndicesStats lib function', () => { const mockClient = { asCurrentUser: { indices: { + exists: jest.fn(), stats: jest.fn(), }, }, asInternalUser: {}, }; const indices = ['test-index-name-1', 'test-index-name-2', 'test-index-name-3']; - const indicesStats = { + const indexStats = { indices: { 'test-index-name-1': { health: 'GREEN', @@ -96,15 +97,11 @@ describe('fetchIndicesStats lib function', () => { }); it('should return hydrated indices', async () => { - mockClient.asCurrentUser.indices.stats.mockImplementationOnce(() => indicesStats); + mockClient.asCurrentUser.indices.exists.mockImplementationOnce(() => true); + mockClient.asCurrentUser.indices.stats.mockImplementationOnce(() => indexStats); await expect( fetchIndicesStats(mockClient as unknown as IScopedClusterClient, indices) ).resolves.toEqual(fetchIndicesStatsResponse); - - expect(mockClient.asCurrentUser.indices.stats).toHaveBeenCalledWith({ - index: indices, - metric: ['docs'], - }); }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.ts b/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.ts index 234fab310cca3..7b436e3dc21b1 100644 --- a/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.ts +++ b/x-pack/plugins/enterprise_search/server/lib/engines/fetch_indices_stats.ts @@ -9,21 +9,23 @@ import { IScopedClusterClient } from '@kbn/core-elasticsearch-server/src/client/ import { EnterpriseSearchEngineIndex } from '../../../common/types/engines'; -export const fetchIndicesStats = async (client: IScopedClusterClient, indices: string[]) => { - const { indices: indicesStats = {} } = await client.asCurrentUser.indices.stats({ - index: indices, +import { availableIndices } from './available_indices'; + +export const fetchIndicesStats = async ( + client: IScopedClusterClient, + indices: string[] +): Promise => { + const indicesStats = await client.asCurrentUser.indices.stats({ + index: await availableIndices(client, indices), metric: ['docs'], }); - const indicesWithStats = indices.map((indexName: string) => { - const indexStats = indicesStats[indexName]; - const hydratedIndex: EnterpriseSearchEngineIndex = { - count: indexStats?.primaries?.docs?.count ?? 0, + return indices.map((index) => { + const indexStats = indicesStats.indices?.[index]; + return { + count: indexStats?.primaries?.docs?.count ?? null, health: indexStats?.health ?? 'unknown', - name: indexName, + name: index, }; - return hydratedIndex; }); - - return indicesWithStats; }; diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts index f69d08b250af9..823e78d9e449d 100644 --- a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts @@ -16,6 +16,7 @@ describe('engines field_capabilities', () => { const mockClient = { asCurrentUser: { fieldCaps: jest.fn(), + indices: { exists: jest.fn() }, }, asInternalUser: {}, }; @@ -44,6 +45,7 @@ describe('engines field_capabilities', () => { indices: ['index-001'], }; + mockClient.asCurrentUser.indices.exists.mockResolvedValueOnce(true); mockClient.asCurrentUser.fieldCaps.mockResolvedValueOnce(fieldCapsResponse); await expect( fetchEngineFieldCapabilities(mockClient as unknown as IScopedClusterClient, mockEngine) diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts index 2494004919714..b2ba5f771e387 100644 --- a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts +++ b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts @@ -14,6 +14,8 @@ import { SchemaField, } from '../../../common/types/engines'; +import { availableIndices } from './available_indices'; + export const fetchEngineFieldCapabilities = async ( client: IScopedClusterClient, engine: EnterpriseSearchEngine @@ -21,9 +23,9 @@ export const fetchEngineFieldCapabilities = async ( const { name, updated_at_millis, indices } = engine; const fieldCapabilities = await client.asCurrentUser.fieldCaps({ fields: '*', - include_unmapped: true, - index: indices, filters: '-metadata', + include_unmapped: true, + index: await availableIndices(client, indices), }); const fields = parseFieldsCapabilities(fieldCapabilities); return {