From 0cd79bf4c9bb134702d52b114c45e7d1dc2ecb21 Mon Sep 17 00:00:00 2001 From: Simeon Widdis Date: Fri, 2 Feb 2024 11:09:32 -0800 Subject: [PATCH] Optimize searches for integration data (#1401) Signed-off-by: Simeon Widdis --- .../repository/index_data_adaptor.ts | 78 ++++++++++++++----- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/server/adaptors/integrations/repository/index_data_adaptor.ts b/server/adaptors/integrations/repository/index_data_adaptor.ts index 3344dd072..f2493ac6c 100644 --- a/server/adaptors/integrations/repository/index_data_adaptor.ts +++ b/server/adaptors/integrations/repository/index_data_adaptor.ts @@ -17,37 +17,79 @@ export class IndexDataAdaptor implements CatalogDataAdaptor { this.client = client; } - private async asJsonAdaptor(): Promise { - const results = await this.client.find({ type: 'integration-template' }); - const filteredIntegrations: SerializedIntegration[] = results.saved_objects - .map((obj) => obj.attributes as SerializedIntegration) - .filter((obj) => this.directory === undefined || this.directory === obj.name); - return new JsonCatalogDataAdaptor(filteredIntegrations); - } - async findIntegrationVersions(dirname?: string | undefined): Promise> { - const adaptor = await this.asJsonAdaptor(); + const integrationVersions = await this.client.find({ + type: 'integration-template', + fields: ['name', 'version'], + search: dirname ? `"${dirname}"` : undefined, + searchFields: ['name'], + }); + const adaptor = new JsonCatalogDataAdaptor( + integrationVersions.saved_objects.map((obj) => obj.attributes as SerializedIntegration) + ); return await adaptor.findIntegrationVersions(dirname); } async readFile(filename: string, type?: IntegrationPart): Promise> { - const adaptor = await this.asJsonAdaptor(); - return await adaptor.readFile(filename, type); + // Duplicates a lot of logic from the Json Adaptor version since we need to parse config + // for an efficient network query anyways + if (type !== undefined) { + return { + ok: false, + error: new Error('JSON adaptor does not support subtypes (isConfigLocalized: true)'), + }; + } + + const filenameParts = filename.match(/([\w]+)-(\d+(\.\d+)*)\.json/); + if (!filenameParts) { + return { ok: false, error: new Error(`Invalid Config filename: ${filename}`) }; + } + + const integrations = await this.client.find({ + type: 'integration-template', + search: `"${filenameParts[1]}" + "${filenameParts[2]}"`, + searchFields: ['name', 'version'], + }); + if (integrations.total === 0) { + return { ok: false, error: new Error('Config file not found: ' + filename) }; + } + + return { ok: true, value: integrations.saved_objects[0].attributes as object }; } - async readFileRaw(filename: string, type?: IntegrationPart): Promise> { - const adaptor = await this.asJsonAdaptor(); - return await adaptor.readFileRaw(filename, type); + async readFileRaw(_filename: string, _type?: IntegrationPart): Promise> { + return { + ok: false, + error: new Error('JSON adaptor does not support raw files (isConfigLocalized: true)'), + }; } async findIntegrations(dirname: string = '.'): Promise> { - const adaptor = await this.asJsonAdaptor(); - return await adaptor.findIntegrations(dirname); + const dir = dirname !== '.' ? dirname : this.directory; + const integrations = await this.client.find({ + type: 'integration-template', + fields: ['name'], + search: dir ? `"${dir}"` : undefined, + searchFields: ['name'], + }); + const names = integrations.saved_objects.map( + (obj) => (obj.attributes as SerializedIntegration).name + ); + return { + ok: true, + value: [...new Set(names)], + }; } async getDirectoryType(dirname?: string): Promise<'integration' | 'repository' | 'unknown'> { - const adaptor = await this.asJsonAdaptor(); - return await adaptor.getDirectoryType(dirname); + const names = await this.findIntegrations(dirname ?? '.'); + if (!names.value || names.value.length === 0) { + return 'unknown'; + } + if (names.value.length === 1) { + return 'integration'; + } + return 'repository'; } join(filename: string): IndexDataAdaptor {