Skip to content

Commit 968bddc

Browse files
authored
Non existing synonyms sets do not fail shard recovery (#125659)
1 parent 6a9d765 commit 968bddc

File tree

8 files changed

+199
-35
lines changed

8 files changed

+199
-35
lines changed

docs/changelog/125659.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 125659
2+
summary: Non existing synonyms sets do not fail shard recovery for indices
3+
area: "Analysis"
4+
type: bug
5+
issues:
6+
- 125603

modules/analysis-common/src/main/java/org/elasticsearch/analysis/common/SynonymTokenFilterFactory.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public ReaderWithOrigin getRulesReader(SynonymTokenFilterFactory factory, IndexC
7272
);
7373
} else {
7474
reader = new ReaderWithOrigin(
75-
Analysis.getReaderFromIndex(synonymsSet, factory.synonymsManagementAPIService),
75+
Analysis.getReaderFromIndex(synonymsSet, factory.synonymsManagementAPIService, factory.lenient),
7676
"[" + synonymsSet + "] synonyms_set in .synonyms index",
7777
synonymsSet
7878
);

qa/mixed-cluster/build.gradle

-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,6 @@ excludeList.add('aggregations/percentiles_hdr_metric/Negative values test')
7070
// sync_id is removed in 9.0
7171
excludeList.add("cat.shards/10_basic/Help")
7272

73-
// Can't work until auto-expand replicas is 0-1 for synonyms index
74-
excludeList.add("synonyms/90_synonyms_reloading_for_synset/Reload analyzers for specific synonym set")
75-
7673
def clusterPath = getPath()
7774

7875
buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName ->

rest-api-spec/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,5 @@ tasks.named("yamlRestCompatTestTransform").configure ({ task ->
8888
task.skipTest("indices.create/21_synthetic_source_stored/field param - keep nested array", "Synthetic source keep arrays now stores leaf arrays natively")
8989
task.skipTest("indices.create/21_synthetic_source_stored/field param - keep root array", "Synthetic source keep arrays now stores leaf arrays natively")
9090
task.skipTest("cluster.info/30_info_thread_pool/Cluster HTTP Info", "The search_throttled thread pool has been removed")
91+
task.skipTest("synonyms/80_synonyms_from_index/Fail loading synonyms from index if synonyms_set doesn't exist", "Synonyms do no longer fail if the synonyms_set doesn't exist")
9192
})

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/110_synonyms_invalid.yml

+156
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,159 @@ setup:
313313
indices.stats: { index: test_index }
314314

315315
- length: { indices: 0 }
316+
317+
---
318+
"Load index with non existent synonyms set":
319+
- requires:
320+
cluster_features: [ index.synonyms_set_lenient_on_non_existing ]
321+
reason: "requires synonyms_set_lenient_on_non_existing bug fix"
322+
- do:
323+
indices.create:
324+
index: test_index
325+
body:
326+
settings:
327+
index:
328+
number_of_shards: 1
329+
number_of_replicas: 0
330+
analysis:
331+
filter:
332+
my_synonym_filter:
333+
type: synonym
334+
synonyms_set: set1
335+
updateable: true
336+
analyzer:
337+
my_analyzer:
338+
type: custom
339+
tokenizer: whitespace
340+
filter: [ lowercase, my_synonym_filter ]
341+
mappings:
342+
properties:
343+
my_field:
344+
type: text
345+
search_analyzer: my_analyzer
346+
347+
- match: { acknowledged: true }
348+
- match: { shards_acknowledged: true }
349+
350+
- do:
351+
indices.stats: { index: test_index }
352+
353+
- match: { indices.test_index.health: "green" }
354+
355+
# Synonyms are not applied
356+
- do:
357+
indices.analyze:
358+
index: test_index
359+
body:
360+
analyzer: my_analyzer
361+
text: foo
362+
363+
- length: { tokens: 1 }
364+
- match: { tokens.0.token: foo }
365+
366+
367+
# Create synonyms set and check synonyms are applied
368+
- do:
369+
synonyms.put_synonym:
370+
id: set1
371+
body:
372+
synonyms_set:
373+
synonyms: "foo => bar, baz"
374+
375+
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
376+
- do:
377+
cluster.health:
378+
index: .synonyms
379+
wait_for_status: green
380+
381+
382+
- do:
383+
indices.stats: { index: test_index }
384+
385+
- match: { indices.test_index.health: "green" }
386+
387+
# Synonyms are applied
388+
- do:
389+
indices.analyze:
390+
index: test_index
391+
body:
392+
analyzer: my_analyzer
393+
text: foo
394+
395+
- length: { tokens: 2 }
396+
397+
---
398+
"Load index with non existent synonyms set and lenient set to false":
399+
- requires:
400+
test_runner_features: [ allowed_warnings ]
401+
402+
- do:
403+
indices.create:
404+
index: test_index
405+
body:
406+
settings:
407+
index:
408+
number_of_shards: 1
409+
number_of_replicas: 0
410+
analysis:
411+
filter:
412+
my_synonym_filter:
413+
type: synonym
414+
synonyms_set: set1
415+
updateable: true
416+
lenient: false
417+
analyzer:
418+
my_analyzer:
419+
type: custom
420+
tokenizer: whitespace
421+
filter: [ lowercase, my_synonym_filter ]
422+
mappings:
423+
properties:
424+
my_field:
425+
type: text
426+
search_analyzer: my_analyzer
427+
428+
- match: { acknowledged: true }
429+
- match: { shards_acknowledged: false }
430+
431+
- do:
432+
indices.stats: { index: test_index }
433+
434+
- length: { indices: 0 }
435+
436+
# Create synonyms set and check synonyms are applied
437+
- do:
438+
synonyms.put_synonym:
439+
id: set1
440+
body:
441+
synonyms_set:
442+
synonyms: "foo => bar, baz"
443+
444+
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
445+
- do:
446+
cluster.health:
447+
index: .synonyms
448+
wait_for_status: green
449+
450+
- do:
451+
# Warning issued in previous versions
452+
allowed_warnings:
453+
- "The [state] field in the response to the reroute API is deprecated and will be removed in a future version. Specify ?metric=none to adopt the future behaviour."
454+
cluster.reroute:
455+
retry_failed: true
456+
457+
- do:
458+
cluster.health:
459+
index: test_index
460+
wait_for_status: green
461+
462+
# Synonyms are applied
463+
- do:
464+
indices.analyze:
465+
index: test_index
466+
body:
467+
analyzer: my_analyzer
468+
text: foo
469+
470+
- length: { tokens: 2 }
471+

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/80_synonyms_from_index.yml

-28
Original file line numberDiff line numberDiff line change
@@ -165,34 +165,6 @@ setup:
165165
query: hola
166166
- match: { hits.total.value: 1 }
167167

168-
---
169-
"Fail loading synonyms from index if synonyms_set doesn't exist":
170-
- do:
171-
indices.create:
172-
index: another_index
173-
body:
174-
settings:
175-
index:
176-
number_of_shards: 1
177-
analysis:
178-
filter:
179-
my_synonym_filter:
180-
type: synonym
181-
synonyms_set: set_missing
182-
updateable: true
183-
analyzer:
184-
my_analyzer:
185-
type: custom
186-
tokenizer: standard
187-
filter: [ lowercase, my_synonym_filter ]
188-
mappings:
189-
properties:
190-
my_field:
191-
type: text
192-
search_analyzer: my_analyzer
193-
- match: { acknowledged: true }
194-
- match: { shards_acknowledged: false }
195-
196168
---
197169
"Load empty synonyms set from index for an analyzer":
198170
- do:

server/src/main/java/org/elasticsearch/index/IndexFeatures.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ public Set<NodeFeature> getFeatures() {
2323

2424
public static final NodeFeature LOGSDB_NO_HOST_NAME_FIELD = new NodeFeature("index.logsdb_no_host_name_field");
2525

26+
private static final NodeFeature SYNONYMS_SET_LENIENT_ON_NON_EXISTING = new NodeFeature("index.synonyms_set_lenient_on_non_existing");
27+
2628
@Override
2729
public Set<NodeFeature> getTestFeatures() {
28-
return Set.of(LOGSDB_NO_HOST_NAME_FIELD);
30+
return Set.of(LOGSDB_NO_HOST_NAME_FIELD, SYNONYMS_SET_LENIENT_ON_NON_EXISTING);
2931
}
3032
}

server/src/main/java/org/elasticsearch/index/analysis/Analysis.java

+32-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.lucene.analysis.th.ThaiAnalyzer;
4949
import org.apache.lucene.analysis.tr.TurkishAnalyzer;
5050
import org.apache.lucene.analysis.util.CSVUtil;
51+
import org.elasticsearch.ResourceNotFoundException;
5152
import org.elasticsearch.action.support.PlainActionFuture;
5253
import org.elasticsearch.common.Strings;
5354
import org.elasticsearch.common.settings.Settings;
@@ -353,10 +354,39 @@ public static Reader getReaderFromFile(Environment env, String filePath, String
353354
}
354355
}
355356

356-
public static Reader getReaderFromIndex(String synonymsSet, SynonymsManagementAPIService synonymsManagementAPIService) {
357+
public static Reader getReaderFromIndex(
358+
String synonymsSet,
359+
SynonymsManagementAPIService synonymsManagementAPIService,
360+
boolean ignoreMissing
361+
) {
357362
final PlainActionFuture<PagedResult<SynonymRule>> synonymsLoadingFuture = new PlainActionFuture<>();
358363
synonymsManagementAPIService.getSynonymSetRules(synonymsSet, synonymsLoadingFuture);
359-
PagedResult<SynonymRule> results = synonymsLoadingFuture.actionGet();
364+
365+
PagedResult<SynonymRule> results;
366+
367+
try {
368+
results = synonymsLoadingFuture.actionGet();
369+
} catch (Exception e) {
370+
if (ignoreMissing == false) {
371+
throw e;
372+
}
373+
374+
boolean notFound = e instanceof ResourceNotFoundException;
375+
String message = String.format(
376+
Locale.ROOT,
377+
"Synonyms set %s %s. Synonyms will not be applied to search results on indices that use this synonym set",
378+
synonymsSet,
379+
notFound ? "not found" : "could not be loaded"
380+
);
381+
382+
if (notFound) {
383+
logger.warn(message);
384+
} else {
385+
logger.error(message, e);
386+
}
387+
388+
results = new PagedResult<>(0, new SynonymRule[0]);
389+
}
360390

361391
SynonymRule[] synonymRules = results.pageResults();
362392
StringBuilder sb = new StringBuilder();

0 commit comments

Comments
 (0)