From 6910b127ba2595c4e4aa6e77f53ef47152ccfbf0 Mon Sep 17 00:00:00 2001 From: Nikolay Marchuk Date: Mon, 21 Jul 2025 18:22:42 +0700 Subject: [PATCH] Handle indexer init mapping errors (#9577) * Retry initMapping for FulltextAdapter Signed-off-by: Nikolay Marchuk * Recreate elastic index when mapping is not compatible Signed-off-by: Nikolay Marchuk * Fix formatting Signed-off-by: Nikolay Marchuk --------- Signed-off-by: Nikolay Marchuk --- pods/fulltext/src/manager.ts | 9 ++++++++- server/elastic/src/adapter.ts | 22 ++++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/pods/fulltext/src/manager.ts b/pods/fulltext/src/manager.ts index e0e6c6ce0d..fccb6a57de 100644 --- a/pods/fulltext/src/manager.ts +++ b/pods/fulltext/src/manager.ts @@ -92,7 +92,14 @@ export class WorkspaceManager { ) this.fulltextAdapter = await this.opt.config.fulltextAdapter.factory(this.opt.config.fulltextAdapter.url) - await this.fulltextAdapter.initMapping(this.ctx) + let adapterInitialized = false + while (!adapterInitialized) { + adapterInitialized = await this.fulltextAdapter.initMapping(this.ctx) + if (!adapterInitialized) { + this.ctx.warn('Failed to initialize indexer mapping, retrying in 5 s') + await new Promise((resolve) => setTimeout(resolve, 5000)) + } + } this.shutdownInterval = setInterval(() => { for (const [k, v] of [...this.indexers.entries()]) { diff --git a/server/elastic/src/adapter.ts b/server/elastic/src/adapter.ts index ad3117cac1..1da9e3711e 100644 --- a/server/elastic/src/adapter.ts +++ b/server/elastic/src/adapter.ts @@ -127,15 +127,29 @@ class ElasticAdapter implements FullTextAdapter { ) const allIndexes = Object.keys(existingVersions.body) const existingOldVersionIndices = allIndexes.filter((name) => name !== indexName) - if (existingOldVersionIndices.length > 0) { + const existsIndex = allIndexes.find((it) => it === indexName) !== undefined + let shouldDropExistingIndex = false + if (existsIndex) { + const mapping = await ctx.with('get-mapping', { indexName }, () => + this.client.indices.getMapping({ + index: indexName + }) + ) + for (const [propName, propType] of Object.entries(mappings.properties)) { + if (mapping.body[indexName]?.mappings.properties?.[propName]?.type !== propType.type) { + shouldDropExistingIndex = true + break + } + } + } + if (existingOldVersionIndices.length > 0 || shouldDropExistingIndex) { await ctx.with('delete-old-index', {}, () => this.client.indices.delete({ - index: existingOldVersionIndices + index: shouldDropExistingIndex ? allIndexes : existingOldVersionIndices }) ) } - const existsIndex = allIndexes.find((it) => it === indexName) !== undefined - if (!existsIndex) { + if (!existsIndex || shouldDropExistingIndex) { await ctx.with('create-index', { indexName }, () => this.client.indices.create({ index: indexName,