mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 17:34:17 -04:00
Synonyms API - Add refresh parameter to check synonyms index and reload analyzers (#126935)
* Add timeout to SynonymsManagementAPIService put synonyms
* Remove replicas 0, as that may impact serverless
* Add timeout to put synonyms action, fix tests
* Fix number of replicas
* Remove cluster.health checks for synonyms index
* Revert debugging
* Add integration test for timeouts
* Use TimeValue instead of an int
* Add YAML tests and REST API specs
* Fix a validation bug in put synonym rule
* Spotless
* Update docs/changelog/126314.yaml
* Remove unnecessary checks for null
* Fix equals / HashCode
* Checks that timeout is passed correctly to the check health method
* Use correctly the default timeout
* spotless
* Add monitor cluster privilege to internal synonyms user
* [CI] Auto commit changes from spotless
* Add capabilities to avoid failing on bwc tests
* Replace timeout for refresh param
* Add param to specs
* Add YAML tests
* Fix changelog
* [CI] Auto commit changes from spotless
* Use BWC serialization tests
* Fix bug in test parser
* Spotless
* Delete doesn't need reloading 🤦 removing it
* Revert "Delete doesn't need reloading 🤦 removing it"
This reverts commit 9c8e0b62be
.
* [CI] Auto commit changes from spotless
* Fix refresh for delete synonym rule
* Fix tests
* Update docs/changelog/126935.yaml
* Add reload analyzers test
* reload_analyzers is not available on serverless
---------
Co-authored-by: elasticsearchmachine <infra-root+elasticsearchmachine@elastic.co>
This commit is contained in:
parent
2ea04a9fed
commit
4d4b962fd1
35 changed files with 719 additions and 191 deletions
6
docs/changelog/126314.yaml
Normal file
6
docs/changelog/126314.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pr: 126314
|
||||||
|
summary: Add refresh to synonyms put / delete APIs to wait for synonyms to be accessible and reload analyzers
|
||||||
|
area: Analysis
|
||||||
|
type: bug
|
||||||
|
issues:
|
||||||
|
- 121441
|
6
docs/changelog/126935.yaml
Normal file
6
docs/changelog/126935.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pr: 126935
|
||||||
|
summary: Synonyms API - Add refresh parameter to check synonyms index and reload analyzers
|
||||||
|
area: Analysis
|
||||||
|
type: enhancement
|
||||||
|
issues:
|
||||||
|
- 121441
|
|
@ -33,6 +33,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"refresh": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Refresh search analyzers to update synonyms"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,12 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"params": {
|
||||||
|
"refresh": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Refresh search analyzers to update synonyms"
|
||||||
|
}
|
||||||
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"description": "Synonyms set rules",
|
"description": "Synonyms set rules",
|
||||||
"required": true
|
"required": true
|
||||||
|
|
|
@ -34,6 +34,12 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"params": {
|
||||||
|
"refresh": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Refresh search analyzers to update synonyms"
|
||||||
|
}
|
||||||
|
},
|
||||||
"body": {
|
"body": {
|
||||||
"description": "Synonym rule",
|
"description": "Synonym rule",
|
||||||
"required": true
|
"required": true
|
||||||
|
|
|
@ -15,11 +15,6 @@ setup:
|
||||||
|
|
||||||
- match: { result: "created" }
|
- match: { result: "created" }
|
||||||
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
synonyms.get_synonym:
|
synonyms.get_synonym:
|
||||||
id: test-update-synonyms
|
id: test-update-synonyms
|
||||||
|
@ -63,11 +58,6 @@ setup:
|
||||||
|
|
||||||
- match: { result: "created" }
|
- match: { result: "created" }
|
||||||
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
synonyms.get_synonym:
|
synonyms.get_synonym:
|
||||||
id: test-empty-synonyms
|
id: test-empty-synonyms
|
||||||
|
@ -75,6 +65,31 @@ setup:
|
||||||
- match: { count: 0 }
|
- match: { count: 0 }
|
||||||
- match: { synonyms_set: [] }
|
- match: { synonyms_set: [] }
|
||||||
|
|
||||||
|
---
|
||||||
|
"Refresh can be specified":
|
||||||
|
|
||||||
|
- requires:
|
||||||
|
test_runner_features: [ capabilities ]
|
||||||
|
capabilities:
|
||||||
|
- method: PUT
|
||||||
|
path: /_synonyms/{rule_id}
|
||||||
|
capabilities: [ synonyms_refresh_param ]
|
||||||
|
reason: "synonyms refresh param capability needed"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
synonyms.put_synonym:
|
||||||
|
id: test-update-synonyms
|
||||||
|
refresh: false
|
||||||
|
body:
|
||||||
|
synonyms_set:
|
||||||
|
- synonyms: "hello, hi"
|
||||||
|
- synonyms: "bye => goodbye"
|
||||||
|
id: "test-id"
|
||||||
|
|
||||||
|
- match: { result: "created" }
|
||||||
|
# Reload analyzers info is not included
|
||||||
|
- not_exists: reload_analyzers_details
|
||||||
|
|
||||||
---
|
---
|
||||||
"Validation fails tests":
|
"Validation fails tests":
|
||||||
- do:
|
- do:
|
||||||
|
@ -116,3 +131,4 @@ setup:
|
||||||
body:
|
body:
|
||||||
synonyms_set:
|
synonyms_set:
|
||||||
- synonyms: "bye, goodbye, "
|
- synonyms: "bye, goodbye, "
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,6 @@ setup:
|
||||||
synonyms_set:
|
synonyms_set:
|
||||||
synonyms: "foo => bar, baz"
|
synonyms: "foo => bar, baz"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
indices.create:
|
indices.create:
|
||||||
index: test_index
|
index: test_index
|
||||||
|
@ -372,13 +366,6 @@ setup:
|
||||||
synonyms_set:
|
synonyms_set:
|
||||||
synonyms: "foo => bar, baz"
|
synonyms: "foo => bar, baz"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
indices.stats: { index: test_index }
|
indices.stats: { index: test_index }
|
||||||
|
|
||||||
|
@ -441,12 +428,6 @@ setup:
|
||||||
synonyms_set:
|
synonyms_set:
|
||||||
synonyms: "foo => bar, baz"
|
synonyms: "foo => bar, baz"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
# Warning issued in previous versions
|
# Warning issued in previous versions
|
||||||
allowed_warnings:
|
allowed_warnings:
|
||||||
|
|
|
@ -14,12 +14,6 @@ setup:
|
||||||
- synonyms: "test => check"
|
- synonyms: "test => check"
|
||||||
id: "test-id-3"
|
id: "test-id-3"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
---
|
---
|
||||||
"Get synonyms set":
|
"Get synonyms set":
|
||||||
- do:
|
- do:
|
||||||
|
|
|
@ -12,12 +12,6 @@ setup:
|
||||||
- synonyms: "bye => goodbye"
|
- synonyms: "bye => goodbye"
|
||||||
id: "test-id-2"
|
id: "test-id-2"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
---
|
---
|
||||||
"Delete synonyms set":
|
"Delete synonyms set":
|
||||||
- do:
|
- do:
|
||||||
|
@ -77,7 +71,6 @@ setup:
|
||||||
settings:
|
settings:
|
||||||
index:
|
index:
|
||||||
number_of_shards: 1
|
number_of_shards: 1
|
||||||
number_of_replicas: 0
|
|
||||||
analysis:
|
analysis:
|
||||||
filter:
|
filter:
|
||||||
my_synonym_filter:
|
my_synonym_filter:
|
||||||
|
|
|
@ -10,12 +10,6 @@ setup:
|
||||||
- synonyms: "hello, hi"
|
- synonyms: "hello, hi"
|
||||||
- synonyms: "goodbye, bye"
|
- synonyms: "goodbye, bye"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
- do:
|
- do:
|
||||||
synonyms.put_synonym:
|
synonyms.put_synonym:
|
||||||
id: test-synonyms-1
|
id: test-synonyms-1
|
||||||
|
|
|
@ -14,12 +14,6 @@ setup:
|
||||||
- synonyms: "test => check"
|
- synonyms: "test => check"
|
||||||
id: "test-id-3"
|
id: "test-id-3"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
---
|
---
|
||||||
"Update a synonyms rule":
|
"Update a synonyms rule":
|
||||||
- do:
|
- do:
|
||||||
|
@ -85,3 +79,68 @@ setup:
|
||||||
rule_id: "test-id-0"
|
rule_id: "test-id-0"
|
||||||
body:
|
body:
|
||||||
synonyms: "i-phone, iphone"
|
synonyms: "i-phone, iphone"
|
||||||
|
|
||||||
|
---
|
||||||
|
"Refresh can be specified":
|
||||||
|
|
||||||
|
- requires:
|
||||||
|
test_runner_features: [ capabilities ]
|
||||||
|
capabilities:
|
||||||
|
- method: PUT
|
||||||
|
path: /_synonyms/{rule_id}
|
||||||
|
capabilities: [ synonyms_refresh_param ]
|
||||||
|
reason: "synonyms refresh param capability needed"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
refresh: false
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-2"
|
||||||
|
body:
|
||||||
|
synonyms: "bye, goodbye, seeya"
|
||||||
|
|
||||||
|
- match: { result: "updated" }
|
||||||
|
# Reload analyzers info is not included
|
||||||
|
- not_exists: reload_analyzers_details
|
||||||
|
|
||||||
|
---
|
||||||
|
"Validation failure tests":
|
||||||
|
- do:
|
||||||
|
catch: /\[synonyms\] field can't be empty/
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-0"
|
||||||
|
body:
|
||||||
|
synonyms: ""
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: /More than one explicit mapping specified in the same synonyms rule/
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-0"
|
||||||
|
body:
|
||||||
|
synonyms: "bye => => goodbye"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: /Incorrect syntax for \[synonyms\]/
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-0"
|
||||||
|
body:
|
||||||
|
synonyms: " => goodbye"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: /Incorrect syntax for \[synonyms\]/
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-0"
|
||||||
|
body:
|
||||||
|
synonyms: "bye => "
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: /Incorrect syntax for \[synonyms\]/
|
||||||
|
synonyms.put_synonym_rule:
|
||||||
|
set_id: "test-synonyms"
|
||||||
|
rule_id: "test-id-0"
|
||||||
|
body:
|
||||||
|
synonyms: "bye, goodbye, "
|
||||||
|
|
|
@ -14,12 +14,6 @@ setup:
|
||||||
- synonyms: "test => check"
|
- synonyms: "test => check"
|
||||||
id: "test-id-3"
|
id: "test-id-3"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
---
|
---
|
||||||
"Get a synonym rule":
|
"Get a synonym rule":
|
||||||
- do:
|
- do:
|
||||||
|
|
|
@ -14,12 +14,6 @@ setup:
|
||||||
- synonyms: "test => check"
|
- synonyms: "test => check"
|
||||||
id: "test-id-3"
|
id: "test-id-3"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
---
|
---
|
||||||
"Delete synonym rule":
|
"Delete synonym rule":
|
||||||
- do:
|
- do:
|
||||||
|
@ -50,6 +44,27 @@ setup:
|
||||||
- synonyms: "test => check"
|
- synonyms: "test => check"
|
||||||
id: "test-id-3"
|
id: "test-id-3"
|
||||||
|
|
||||||
|
---
|
||||||
|
"Refresh can be specified":
|
||||||
|
|
||||||
|
- requires:
|
||||||
|
test_runner_features: [ capabilities ]
|
||||||
|
capabilities:
|
||||||
|
- method: PUT
|
||||||
|
path: /_synonyms/{rule_id}
|
||||||
|
capabilities: [ synonyms_refresh_param ]
|
||||||
|
reason: "synonyms refresh param capability needed"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
synonyms.delete_synonym_rule:
|
||||||
|
set_id: test-synonyms
|
||||||
|
rule_id: test-id-2
|
||||||
|
refresh: false
|
||||||
|
|
||||||
|
- match: { result: "deleted" }
|
||||||
|
# Reload analyzers info is not included
|
||||||
|
- not_exists: reload_analyzers_details
|
||||||
|
|
||||||
---
|
---
|
||||||
"Delete synonym rule - missing synonym set":
|
"Delete synonym rule - missing synonym set":
|
||||||
- do:
|
- do:
|
||||||
|
|
|
@ -13,12 +13,6 @@ setup:
|
||||||
- synonyms: "bye => goodbye"
|
- synonyms: "bye => goodbye"
|
||||||
id: "synonym-rule-2"
|
id: "synonym-rule-2"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
# Create an index with synonym_filter that uses that synonyms set
|
# Create an index with synonym_filter that uses that synonyms set
|
||||||
- do:
|
- do:
|
||||||
indices.create:
|
indices.create:
|
||||||
|
|
|
@ -14,12 +14,6 @@ setup:
|
||||||
- synonyms: "bye => goodbye"
|
- synonyms: "bye => goodbye"
|
||||||
id: "synonym-rule-2"
|
id: "synonym-rule-2"
|
||||||
|
|
||||||
# This is to ensure that all index shards (write and read) are available. In serverless this can take some time.
|
|
||||||
- do:
|
|
||||||
cluster.health:
|
|
||||||
index: .synonyms
|
|
||||||
wait_for_status: green
|
|
||||||
|
|
||||||
# Create synonyms synonyms_set2
|
# Create synonyms synonyms_set2
|
||||||
- do:
|
- do:
|
||||||
synonyms.put_synonym:
|
synonyms.put_synonym:
|
||||||
|
@ -156,3 +150,62 @@ setup:
|
||||||
my_field:
|
my_field:
|
||||||
query: salute
|
query: salute
|
||||||
- match: { hits.total.value: 0 }
|
- match: { hits.total.value: 0 }
|
||||||
|
|
||||||
|
---
|
||||||
|
"Reload analyzers with refresh false":
|
||||||
|
- requires:
|
||||||
|
test_runner_features: [ capabilities ]
|
||||||
|
capabilities:
|
||||||
|
- method: PUT
|
||||||
|
path: /_synonyms/{rule_id}
|
||||||
|
capabilities: [ synonyms_refresh_param ]
|
||||||
|
reason: "synonyms refresh param capability needed"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
synonyms.put_synonym:
|
||||||
|
id: synonyms_set1
|
||||||
|
refresh: false
|
||||||
|
body:
|
||||||
|
synonyms_set:
|
||||||
|
- synonyms: "hello, salute"
|
||||||
|
|
||||||
|
- match: { result: "updated" }
|
||||||
|
- not_exists: reload_analyzers_details
|
||||||
|
|
||||||
|
# Confirm that the index analyzers are not reloaded for my_index1
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
index: my_index1
|
||||||
|
body:
|
||||||
|
query:
|
||||||
|
match:
|
||||||
|
my_field:
|
||||||
|
query: salute
|
||||||
|
- match: { hits.total.value: 0 }
|
||||||
|
|
||||||
|
# Reloading analyzers makes synonyms refresh
|
||||||
|
- do:
|
||||||
|
synonyms.put_synonym:
|
||||||
|
id: synonyms_set1
|
||||||
|
refresh: true
|
||||||
|
body:
|
||||||
|
synonyms_set:
|
||||||
|
- synonyms: "hello, salute"
|
||||||
|
- synonyms: "ciao => goodbye"
|
||||||
|
|
||||||
|
- match: { result: "updated" }
|
||||||
|
- gt: { reload_analyzers_details._shards.total: 0 }
|
||||||
|
- gt: { reload_analyzers_details._shards.successful: 0 }
|
||||||
|
- length: { reload_analyzers_details.reload_details: 1 }
|
||||||
|
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
index: my_index1
|
||||||
|
body:
|
||||||
|
query:
|
||||||
|
match:
|
||||||
|
my_field:
|
||||||
|
query: salute
|
||||||
|
|
||||||
|
- match: { hits.total.value: 1 }
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,12 @@ package org.elasticsearch.synonyms;
|
||||||
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||||
import org.elasticsearch.action.bulk.BulkResponse;
|
import org.elasticsearch.action.bulk.BulkResponse;
|
||||||
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
import org.elasticsearch.index.mapper.extras.MapperExtrasPlugin;
|
import org.elasticsearch.index.mapper.extras.MapperExtrasPlugin;
|
||||||
|
import org.elasticsearch.indices.IndexCreationException;
|
||||||
import org.elasticsearch.plugins.Plugin;
|
import org.elasticsearch.plugins.Plugin;
|
||||||
import org.elasticsearch.reindex.ReindexPlugin;
|
import org.elasticsearch.reindex.ReindexPlugin;
|
||||||
import org.elasticsearch.test.ESIntegTestCase;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
|
@ -50,22 +54,29 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
public void testCreateManySynonyms() throws Exception {
|
public void testCreateManySynonyms() throws Exception {
|
||||||
CountDownLatch putLatch = new CountDownLatch(1);
|
CountDownLatch putLatch = new CountDownLatch(1);
|
||||||
String synonymSetId = randomIdentifier();
|
String synonymSetId = randomIdentifier();
|
||||||
|
boolean refresh = randomBoolean();
|
||||||
int rulesNumber = randomIntBetween(maxSynonymSets / 2, maxSynonymSets);
|
int rulesNumber = randomIntBetween(maxSynonymSets / 2, maxSynonymSets);
|
||||||
synonymsManagementAPIService.putSynonymsSet(synonymSetId, randomSynonymsSet(rulesNumber, rulesNumber), new ActionListener<>() {
|
synonymsManagementAPIService.putSynonymsSet(
|
||||||
@Override
|
synonymSetId,
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
randomSynonymsSet(rulesNumber, rulesNumber),
|
||||||
assertEquals(
|
refresh,
|
||||||
SynonymsManagementAPIService.UpdateSynonymsResultStatus.CREATED,
|
new ActionListener<>() {
|
||||||
synonymsReloadResult.synonymsOperationResult()
|
@Override
|
||||||
);
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
putLatch.countDown();
|
assertEquals(
|
||||||
}
|
SynonymsManagementAPIService.UpdateSynonymsResultStatus.CREATED,
|
||||||
|
synonymsReloadResult.synonymsOperationResult()
|
||||||
|
);
|
||||||
|
assertEquals(refresh, synonymsReloadResult.reloadAnalyzersResponse() != null);
|
||||||
|
putLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Exception e) {
|
public void onFailure(Exception e) {
|
||||||
fail(e);
|
fail(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
putLatch.await(5, TimeUnit.SECONDS);
|
putLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
@ -95,6 +106,7 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
synonymsManagementAPIService.putSynonymsSet(
|
synonymsManagementAPIService.putSynonymsSet(
|
||||||
randomIdentifier(),
|
randomIdentifier(),
|
||||||
randomSynonymsSet(maxSynonymSets + 1, maxSynonymSets * 2),
|
randomSynonymsSet(maxSynonymSets + 1, maxSynonymSets * 2),
|
||||||
|
randomBoolean(),
|
||||||
new ActionListener<>() {
|
new ActionListener<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
@ -120,67 +132,73 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
int rulesToUpdate = randomIntBetween(1, 10);
|
int rulesToUpdate = randomIntBetween(1, 10);
|
||||||
int synonymsToCreate = maxSynonymSets - rulesToUpdate;
|
int synonymsToCreate = maxSynonymSets - rulesToUpdate;
|
||||||
String synonymSetId = randomIdentifier();
|
String synonymSetId = randomIdentifier();
|
||||||
synonymsManagementAPIService.putSynonymsSet(synonymSetId, randomSynonymsSet(synonymsToCreate), new ActionListener<>() {
|
synonymsManagementAPIService.putSynonymsSet(
|
||||||
@Override
|
synonymSetId,
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
randomSynonymsSet(synonymsToCreate),
|
||||||
// Create as many rules as should fail
|
randomBoolean(),
|
||||||
SynonymRule[] rules = randomSynonymsSet(atLeast(rulesToUpdate + 1));
|
new ActionListener<>() {
|
||||||
CountDownLatch updatedRulesLatch = new CountDownLatch(rulesToUpdate);
|
@Override
|
||||||
for (int i = 0; i < rulesToUpdate; i++) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
synonymsManagementAPIService.putSynonymRule(synonymSetId, rules[i], new ActionListener<>() {
|
// Create as many rules as should fail
|
||||||
@Override
|
SynonymRule[] rules = randomSynonymsSet(atLeast(rulesToUpdate + 1));
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
CountDownLatch updatedRulesLatch = new CountDownLatch(rulesToUpdate);
|
||||||
updatedRulesLatch.countDown();
|
for (int i = 0; i < rulesToUpdate; i++) {
|
||||||
}
|
synonymsManagementAPIService.putSynonymRule(synonymSetId, rules[i], true, new ActionListener<>() {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Exception e) {
|
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
updatedRulesLatch.await(5, TimeUnit.SECONDS);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updating more rules fails
|
|
||||||
int rulesToInsert = rules.length - rulesToUpdate;
|
|
||||||
CountDownLatch insertRulesLatch = new CountDownLatch(rulesToInsert);
|
|
||||||
for (int i = rulesToUpdate; i < rulesToInsert; i++) {
|
|
||||||
synonymsManagementAPIService.putSynonymRule(
|
|
||||||
// Error here
|
|
||||||
synonymSetId,
|
|
||||||
rules[i],
|
|
||||||
new ActionListener<>() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
fail("Shouldn't have been able to update a rule");
|
updatedRulesLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(Exception e) {
|
public void onFailure(Exception e) {
|
||||||
if (e instanceof IllegalArgumentException == false) {
|
fail(e);
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
updatedRulesLatch.countDown();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
}
|
||||||
|
try {
|
||||||
|
updatedRulesLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updating more rules fails
|
||||||
|
int rulesToInsert = rules.length - rulesToUpdate;
|
||||||
|
CountDownLatch insertRulesLatch = new CountDownLatch(rulesToInsert);
|
||||||
|
for (int i = rulesToUpdate; i < rulesToInsert; i++) {
|
||||||
|
synonymsManagementAPIService.putSynonymRule(
|
||||||
|
// Error here
|
||||||
|
synonymSetId,
|
||||||
|
rules[i],
|
||||||
|
randomBoolean(),
|
||||||
|
new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
fail("Shouldn't have been able to update a rule");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
if (e instanceof IllegalArgumentException == false) {
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
updatedRulesLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
insertRulesLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
insertRulesLatch.await(5, TimeUnit.SECONDS);
|
@Override
|
||||||
} catch (InterruptedException e) {
|
public void onFailure(Exception e) {
|
||||||
fail(e);
|
fail(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
@Override
|
|
||||||
public void onFailure(Exception e) {
|
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
latch.await(5, TimeUnit.SECONDS);
|
latch.await(5, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
@ -189,13 +207,14 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
String synonymSetId = randomIdentifier();
|
String synonymSetId = randomIdentifier();
|
||||||
SynonymRule[] synonymsSet = randomSynonymsSet(maxSynonymSets, maxSynonymSets);
|
SynonymRule[] synonymsSet = randomSynonymsSet(maxSynonymSets, maxSynonymSets);
|
||||||
synonymsManagementAPIService.putSynonymsSet(synonymSetId, synonymsSet, new ActionListener<>() {
|
synonymsManagementAPIService.putSynonymsSet(synonymSetId, synonymsSet, true, new ActionListener<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
// Updating a rule fails
|
// Updating a rule fails
|
||||||
synonymsManagementAPIService.putSynonymRule(
|
synonymsManagementAPIService.putSynonymRule(
|
||||||
synonymSetId,
|
synonymSetId,
|
||||||
synonymsSet[randomIntBetween(0, maxSynonymSets - 1)],
|
synonymsSet[randomIntBetween(0, maxSynonymSets - 1)],
|
||||||
|
randomBoolean(),
|
||||||
new ActionListener<>() {
|
new ActionListener<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
@ -224,11 +243,11 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
String synonymSetId = randomIdentifier();
|
String synonymSetId = randomIdentifier();
|
||||||
String ruleId = randomIdentifier();
|
String ruleId = randomIdentifier();
|
||||||
SynonymRule[] synonymsSet = randomSynonymsSet(maxSynonymSets, maxSynonymSets);
|
SynonymRule[] synonymsSet = randomSynonymsSet(maxSynonymSets, maxSynonymSets);
|
||||||
synonymsManagementAPIService.putSynonymsSet(synonymSetId, synonymsSet, new ActionListener<>() {
|
synonymsManagementAPIService.putSynonymsSet(synonymSetId, synonymsSet, randomBoolean(), new ActionListener<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
// Updating a rule fails
|
// Updating a rule fails
|
||||||
synonymsManagementAPIService.putSynonymRule(synonymSetId, randomSynonymRule(ruleId), new ActionListener<>() {
|
synonymsManagementAPIService.putSynonymRule(synonymSetId, randomSynonymRule(ruleId), true, new ActionListener<>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
fail("Should not create a new rule that does not exist when at max capacity");
|
fail("Should not create a new rule that does not exist when at max capacity");
|
||||||
|
@ -289,4 +308,113 @@ public class SynonymsManagementAPIServiceIT extends ESIntegTestCase {
|
||||||
readLatch.await(5, TimeUnit.SECONDS);
|
readLatch.await(5, TimeUnit.SECONDS);
|
||||||
verify(logger).warn(anyString(), eq(synonymSetId));
|
verify(logger).warn(anyString(), eq(synonymSetId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateSynonymsWithYellowSynonymsIndex() throws Exception {
|
||||||
|
|
||||||
|
// Override health method check to simulate a timeout in checking the synonyms index
|
||||||
|
synonymsManagementAPIService = new SynonymsManagementAPIService(client()) {
|
||||||
|
@Override
|
||||||
|
void checkSynonymsIndexHealth(ActionListener<ClusterHealthResponse> listener) {
|
||||||
|
ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT).build();
|
||||||
|
ClusterHealthResponse response = new ClusterHealthResponse(
|
||||||
|
randomIdentifier(),
|
||||||
|
new String[] { SynonymsManagementAPIService.SYNONYMS_INDEX_CONCRETE_NAME },
|
||||||
|
clusterState
|
||||||
|
);
|
||||||
|
response.setTimedOut(true);
|
||||||
|
listener.onResponse(response);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a rule fails
|
||||||
|
CountDownLatch putLatch = new CountDownLatch(1);
|
||||||
|
String synonymSetId = randomIdentifier();
|
||||||
|
synonymsManagementAPIService.putSynonymsSet(synonymSetId, randomSynonymsSet(1, 1), true, new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
fail("Shouldn't have been able to create synonyms with refresh in synonyms index health");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
// Expected
|
||||||
|
assertTrue(e instanceof IndexCreationException);
|
||||||
|
assertTrue(e.getMessage().contains("synonyms index [.synonyms] is not searchable"));
|
||||||
|
putLatch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
putLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// Update a rule fails
|
||||||
|
CountDownLatch updateLatch = new CountDownLatch(1);
|
||||||
|
String synonymRuleId = randomIdentifier();
|
||||||
|
synonymsManagementAPIService.putSynonymRule(synonymSetId, randomSynonymRule(synonymRuleId), true, new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
fail("Shouldn't have been able to update synonyms with refresh in synonyms index health");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
// Expected
|
||||||
|
assertTrue(e instanceof IndexCreationException);
|
||||||
|
assertTrue(e.getMessage().contains("synonyms index [.synonyms] is not searchable"));
|
||||||
|
updateLatch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
updateLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// Delete a rule does not fail
|
||||||
|
CountDownLatch deleteLatch = new CountDownLatch(1);
|
||||||
|
synonymsManagementAPIService.deleteSynonymRule(synonymSetId, synonymRuleId, true, new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
updateLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
// Expected
|
||||||
|
fail("Should have been able to delete a synonym rule");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// But, we can still create a synonyms set without refresh
|
||||||
|
CountDownLatch putNoRefreshLatch = new CountDownLatch(1);
|
||||||
|
synonymsManagementAPIService.putSynonymsSet(synonymSetId, randomSynonymsSet(1, 1), false, new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
// Expected
|
||||||
|
putLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
putNoRefreshLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
// Same for update
|
||||||
|
CountDownLatch putRuleNoRefreshLatch = new CountDownLatch(1);
|
||||||
|
synonymsManagementAPIService.putSynonymRule(synonymSetId, randomSynonymRule(synonymRuleId), false, new ActionListener<>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(SynonymsManagementAPIService.SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
// Expected
|
||||||
|
putRuleNoRefreshLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
putRuleNoRefreshLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,7 @@ public class TransportVersions {
|
||||||
public static final TransportVersion BATCHED_QUERY_EXECUTION_DELAYABLE_WRITABLE = def(9_057_0_00);
|
public static final TransportVersion BATCHED_QUERY_EXECUTION_DELAYABLE_WRITABLE = def(9_057_0_00);
|
||||||
public static final TransportVersion SEARCH_INCREMENTAL_TOP_DOCS_NULL = def(9_058_0_00);
|
public static final TransportVersion SEARCH_INCREMENTAL_TOP_DOCS_NULL = def(9_058_0_00);
|
||||||
public static final TransportVersion COMPRESS_DELAYABLE_WRITEABLE = def(9_059_0_00);
|
public static final TransportVersion COMPRESS_DELAYABLE_WRITEABLE = def(9_059_0_00);
|
||||||
|
public static final TransportVersion SYNONYMS_REFRESH_PARAM = def(9_060_0_00);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* STOP! READ THIS FIRST! No, really,
|
* STOP! READ THIS FIRST! No, really,
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.synonyms;
|
package org.elasticsearch.action.synonyms;
|
||||||
|
|
||||||
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.action.ActionRequest;
|
import org.elasticsearch.action.ActionRequest;
|
||||||
import org.elasticsearch.action.ActionRequestValidationException;
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.ActionType;
|
import org.elasticsearch.action.ActionType;
|
||||||
|
@ -31,18 +32,24 @@ public class DeleteSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
|
|
||||||
public static class Request extends ActionRequest {
|
public static class Request extends ActionRequest {
|
||||||
private final String synonymsSetId;
|
private final String synonymsSetId;
|
||||||
|
|
||||||
private final String synonymRuleId;
|
private final String synonymRuleId;
|
||||||
|
private final boolean refresh;
|
||||||
|
|
||||||
public Request(StreamInput in) throws IOException {
|
public Request(StreamInput in) throws IOException {
|
||||||
super(in);
|
super(in);
|
||||||
this.synonymsSetId = in.readString();
|
this.synonymsSetId = in.readString();
|
||||||
this.synonymRuleId = in.readString();
|
this.synonymRuleId = in.readString();
|
||||||
|
if (in.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
this.refresh = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
this.refresh = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request(String synonymsSetId, String synonymRuleId) {
|
public Request(String synonymsSetId, String synonymRuleId, boolean refresh) {
|
||||||
this.synonymsSetId = synonymsSetId;
|
this.synonymsSetId = synonymsSetId;
|
||||||
this.synonymRuleId = synonymRuleId;
|
this.synonymRuleId = synonymRuleId;
|
||||||
|
this.refresh = refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,6 +70,9 @@ public class DeleteSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
super.writeTo(out);
|
super.writeTo(out);
|
||||||
out.writeString(synonymsSetId);
|
out.writeString(synonymsSetId);
|
||||||
out.writeString(synonymRuleId);
|
out.writeString(synonymRuleId);
|
||||||
|
if (out.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
out.writeBoolean(refresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String synonymsSetId() {
|
public String synonymsSetId() {
|
||||||
|
@ -73,6 +83,10 @@ public class DeleteSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
return synonymRuleId;
|
return synonymRuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean refresh() {
|
||||||
|
return refresh;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.synonyms;
|
package org.elasticsearch.action.synonyms;
|
||||||
|
|
||||||
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.action.ActionRequest;
|
import org.elasticsearch.action.ActionRequest;
|
||||||
import org.elasticsearch.action.ActionRequestValidationException;
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.ActionType;
|
import org.elasticsearch.action.ActionType;
|
||||||
|
@ -40,8 +41,8 @@ public class PutSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
|
|
||||||
public static class Request extends ActionRequest {
|
public static class Request extends ActionRequest {
|
||||||
private final String synonymsSetId;
|
private final String synonymsSetId;
|
||||||
|
|
||||||
private final SynonymRule synonymRule;
|
private final SynonymRule synonymRule;
|
||||||
|
private final boolean refresh;
|
||||||
|
|
||||||
public static final ParseField SYNONYMS_FIELD = new ParseField(SynonymsManagementAPIService.SYNONYMS_FIELD);
|
public static final ParseField SYNONYMS_FIELD = new ParseField(SynonymsManagementAPIService.SYNONYMS_FIELD);
|
||||||
private static final ConstructingObjectParser<SynonymRule, String> PARSER = new ConstructingObjectParser<>(
|
private static final ConstructingObjectParser<SynonymRule, String> PARSER = new ConstructingObjectParser<>(
|
||||||
|
@ -58,20 +59,28 @@ public class PutSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
super(in);
|
super(in);
|
||||||
this.synonymsSetId = in.readString();
|
this.synonymsSetId = in.readString();
|
||||||
this.synonymRule = new SynonymRule(in);
|
this.synonymRule = new SynonymRule(in);
|
||||||
|
if (in.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
this.refresh = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
this.refresh = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request(String synonymsSetId, String synonymRuleId, BytesReference content, XContentType contentType) throws IOException {
|
public Request(String synonymsSetId, String synonymRuleId, boolean refresh, BytesReference content, XContentType contentType)
|
||||||
|
throws IOException {
|
||||||
this.synonymsSetId = synonymsSetId;
|
this.synonymsSetId = synonymsSetId;
|
||||||
try (XContentParser parser = XContentHelper.createParser(XContentParserConfiguration.EMPTY, content, contentType)) {
|
try (XContentParser parser = XContentHelper.createParser(XContentParserConfiguration.EMPTY, content, contentType)) {
|
||||||
this.synonymRule = PARSER.apply(parser, synonymRuleId);
|
this.synonymRule = PARSER.apply(parser, synonymRuleId);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("Failed to parse: " + content.utf8ToString(), e);
|
throw new IllegalArgumentException("Failed to parse: " + content.utf8ToString(), e);
|
||||||
}
|
}
|
||||||
|
this.refresh = refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
Request(String synonymsSetId, SynonymRule synonymRule) {
|
Request(String synonymsSetId, SynonymRule synonymRule, boolean refresh) {
|
||||||
this.synonymsSetId = synonymsSetId;
|
this.synonymsSetId = synonymsSetId;
|
||||||
this.synonymRule = synonymRule;
|
this.synonymRule = synonymRule;
|
||||||
|
this.refresh = refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -96,6 +105,9 @@ public class PutSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
super.writeTo(out);
|
super.writeTo(out);
|
||||||
out.writeString(synonymsSetId);
|
out.writeString(synonymsSetId);
|
||||||
synonymRule.writeTo(out);
|
synonymRule.writeTo(out);
|
||||||
|
if (out.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
out.writeBoolean(refresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String synonymsSetId() {
|
public String synonymsSetId() {
|
||||||
|
@ -106,17 +118,23 @@ public class PutSynonymRuleAction extends ActionType<SynonymUpdateResponse> {
|
||||||
return synonymRule;
|
return synonymRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean refresh() {
|
||||||
|
return refresh;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Request request = (Request) o;
|
Request request = (Request) o;
|
||||||
return Objects.equals(synonymsSetId, request.synonymsSetId) && Objects.equals(synonymRule, request.synonymRule);
|
return Objects.equals(refresh, request.refresh)
|
||||||
|
&& Objects.equals(synonymsSetId, request.synonymsSetId)
|
||||||
|
&& Objects.equals(synonymRule, request.synonymRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(synonymsSetId, synonymRule);
|
return Objects.hash(synonymsSetId, synonymRule, refresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.synonyms;
|
package org.elasticsearch.action.synonyms;
|
||||||
|
|
||||||
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.action.ActionRequest;
|
import org.elasticsearch.action.ActionRequest;
|
||||||
import org.elasticsearch.action.ActionRequestValidationException;
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.ActionType;
|
import org.elasticsearch.action.ActionType;
|
||||||
|
@ -43,6 +44,7 @@ public class PutSynonymsAction extends ActionType<SynonymUpdateResponse> {
|
||||||
public static class Request extends ActionRequest {
|
public static class Request extends ActionRequest {
|
||||||
private final String synonymsSetId;
|
private final String synonymsSetId;
|
||||||
private final SynonymRule[] synonymRules;
|
private final SynonymRule[] synonymRules;
|
||||||
|
private final boolean refresh;
|
||||||
|
|
||||||
public static final ParseField SYNONYMS_SET_FIELD = new ParseField(SynonymsManagementAPIService.SYNONYMS_SET_FIELD);
|
public static final ParseField SYNONYMS_SET_FIELD = new ParseField(SynonymsManagementAPIService.SYNONYMS_SET_FIELD);
|
||||||
private static final ConstructingObjectParser<SynonymRule[], Void> PARSER = new ConstructingObjectParser<>("synonyms_set", args -> {
|
private static final ConstructingObjectParser<SynonymRule[], Void> PARSER = new ConstructingObjectParser<>("synonyms_set", args -> {
|
||||||
|
@ -59,10 +61,16 @@ public class PutSynonymsAction extends ActionType<SynonymUpdateResponse> {
|
||||||
super(in);
|
super(in);
|
||||||
this.synonymsSetId = in.readString();
|
this.synonymsSetId = in.readString();
|
||||||
this.synonymRules = in.readArray(SynonymRule::new, SynonymRule[]::new);
|
this.synonymRules = in.readArray(SynonymRule::new, SynonymRule[]::new);
|
||||||
|
if (in.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
this.refresh = in.readBoolean();
|
||||||
|
} else {
|
||||||
|
this.refresh = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request(String synonymsSetId, BytesReference content, XContentType contentType) throws IOException {
|
public Request(String synonymsSetId, boolean refresh, BytesReference content, XContentType contentType) throws IOException {
|
||||||
this.synonymsSetId = synonymsSetId;
|
this.synonymsSetId = synonymsSetId;
|
||||||
|
this.refresh = refresh;
|
||||||
try (XContentParser parser = XContentHelper.createParser(XContentParserConfiguration.EMPTY, content, contentType)) {
|
try (XContentParser parser = XContentHelper.createParser(XContentParserConfiguration.EMPTY, content, contentType)) {
|
||||||
this.synonymRules = PARSER.apply(parser, null);
|
this.synonymRules = PARSER.apply(parser, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -70,9 +78,10 @@ public class PutSynonymsAction extends ActionType<SynonymUpdateResponse> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Request(String synonymsSetId, SynonymRule[] synonymRules) {
|
Request(String synonymsSetId, SynonymRule[] synonymRules, boolean refresh) {
|
||||||
this.synonymsSetId = synonymsSetId;
|
this.synonymsSetId = synonymsSetId;
|
||||||
this.synonymRules = synonymRules;
|
this.synonymRules = synonymRules;
|
||||||
|
this.refresh = refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -95,12 +104,19 @@ public class PutSynonymsAction extends ActionType<SynonymUpdateResponse> {
|
||||||
super.writeTo(out);
|
super.writeTo(out);
|
||||||
out.writeString(synonymsSetId);
|
out.writeString(synonymsSetId);
|
||||||
out.writeArray(synonymRules);
|
out.writeArray(synonymRules);
|
||||||
|
if (out.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
out.writeBoolean(refresh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String synonymsSetId() {
|
public String synonymsSetId() {
|
||||||
return synonymsSetId;
|
return synonymsSetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean refresh() {
|
||||||
|
return refresh;
|
||||||
|
}
|
||||||
|
|
||||||
public SynonymRule[] synonymRules() {
|
public SynonymRule[] synonymRules() {
|
||||||
return synonymRules;
|
return synonymRules;
|
||||||
}
|
}
|
||||||
|
@ -110,12 +126,14 @@ public class PutSynonymsAction extends ActionType<SynonymUpdateResponse> {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Request request = (Request) o;
|
Request request = (Request) o;
|
||||||
return Objects.equals(synonymsSetId, request.synonymsSetId) && Arrays.equals(synonymRules, request.synonymRules);
|
return Objects.equals(refresh, request.refresh)
|
||||||
|
&& Objects.equals(synonymsSetId, request.synonymsSetId)
|
||||||
|
&& Arrays.equals(synonymRules, request.synonymRules);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(synonymsSetId, Arrays.hashCode(synonymRules));
|
return Objects.hash(synonymsSetId, Arrays.hashCode(synonymRules), refresh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.synonyms;
|
package org.elasticsearch.action.synonyms;
|
||||||
|
|
||||||
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.action.ActionResponse;
|
import org.elasticsearch.action.ActionResponse;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
@ -20,17 +21,27 @@ import org.elasticsearch.xcontent.ToXContentObject;
|
||||||
import org.elasticsearch.xcontent.XContentBuilder;
|
import org.elasticsearch.xcontent.XContentBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SynonymUpdateResponse extends ActionResponse implements ToXContentObject {
|
public class SynonymUpdateResponse extends ActionResponse implements ToXContentObject {
|
||||||
|
|
||||||
|
public static final String RESULT_FIELD = "result";
|
||||||
|
public static final String RELOAD_ANALYZERS_DETAILS_FIELD = "reload_analyzers_details";
|
||||||
|
static final ReloadAnalyzersResponse EMPTY_RELOAD_ANALYZER_RESPONSE = new ReloadAnalyzersResponse(0, 0, 0, List.of(), Map.of());
|
||||||
|
|
||||||
private final UpdateSynonymsResultStatus updateStatus;
|
private final UpdateSynonymsResultStatus updateStatus;
|
||||||
private final ReloadAnalyzersResponse reloadAnalyzersResponse;
|
private final ReloadAnalyzersResponse reloadAnalyzersResponse;
|
||||||
|
|
||||||
public SynonymUpdateResponse(StreamInput in) throws IOException {
|
public SynonymUpdateResponse(StreamInput in) throws IOException {
|
||||||
this.updateStatus = in.readEnum(UpdateSynonymsResultStatus.class);
|
this.updateStatus = in.readEnum(UpdateSynonymsResultStatus.class);
|
||||||
this.reloadAnalyzersResponse = new ReloadAnalyzersResponse(in);
|
if (in.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
this.reloadAnalyzersResponse = in.readOptionalWriteable(ReloadAnalyzersResponse::new);
|
||||||
|
} else {
|
||||||
|
this.reloadAnalyzersResponse = new ReloadAnalyzersResponse(in);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public SynonymUpdateResponse(SynonymsReloadResult synonymsReloadResult) {
|
public SynonymUpdateResponse(SynonymsReloadResult synonymsReloadResult) {
|
||||||
|
@ -38,7 +49,6 @@ public class SynonymUpdateResponse extends ActionResponse implements ToXContentO
|
||||||
UpdateSynonymsResultStatus updateStatus = synonymsReloadResult.synonymsOperationResult();
|
UpdateSynonymsResultStatus updateStatus = synonymsReloadResult.synonymsOperationResult();
|
||||||
Objects.requireNonNull(updateStatus, "Update status must not be null");
|
Objects.requireNonNull(updateStatus, "Update status must not be null");
|
||||||
ReloadAnalyzersResponse reloadResponse = synonymsReloadResult.reloadAnalyzersResponse();
|
ReloadAnalyzersResponse reloadResponse = synonymsReloadResult.reloadAnalyzersResponse();
|
||||||
Objects.requireNonNull(reloadResponse, "Reload analyzers response must not be null");
|
|
||||||
|
|
||||||
this.updateStatus = updateStatus;
|
this.updateStatus = updateStatus;
|
||||||
this.reloadAnalyzersResponse = reloadResponse;
|
this.reloadAnalyzersResponse = reloadResponse;
|
||||||
|
@ -48,9 +58,11 @@ public class SynonymUpdateResponse extends ActionResponse implements ToXContentO
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
{
|
{
|
||||||
builder.field("result", updateStatus.name().toLowerCase(Locale.ENGLISH));
|
builder.field(RESULT_FIELD, updateStatus.name().toLowerCase(Locale.ENGLISH));
|
||||||
builder.field("reload_analyzers_details");
|
if (reloadAnalyzersResponse != null) {
|
||||||
reloadAnalyzersResponse.toXContent(builder, params);
|
builder.field(RELOAD_ANALYZERS_DETAILS_FIELD);
|
||||||
|
reloadAnalyzersResponse.toXContent(builder, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
|
|
||||||
|
@ -60,7 +72,16 @@ public class SynonymUpdateResponse extends ActionResponse implements ToXContentO
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
out.writeEnum(updateStatus);
|
out.writeEnum(updateStatus);
|
||||||
reloadAnalyzersResponse.writeTo(out);
|
if (out.getTransportVersion().onOrAfter(TransportVersions.SYNONYMS_REFRESH_PARAM)) {
|
||||||
|
out.writeOptionalWriteable(reloadAnalyzersResponse);
|
||||||
|
} else {
|
||||||
|
if (reloadAnalyzersResponse == null) {
|
||||||
|
// Nulls will be written as empty reload analyzer responses for older versions
|
||||||
|
EMPTY_RELOAD_ANALYZER_RESPONSE.writeTo(out);
|
||||||
|
} else {
|
||||||
|
reloadAnalyzersResponse.writeTo(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestStatus status() {
|
public RestStatus status() {
|
||||||
|
@ -70,6 +91,14 @@ public class SynonymUpdateResponse extends ActionResponse implements ToXContentO
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateSynonymsResultStatus updateStatus() {
|
||||||
|
return updateStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReloadAnalyzersResponse reloadAnalyzersResponse() {
|
||||||
|
return reloadAnalyzersResponse;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
|
|
|
@ -41,6 +41,7 @@ public class TransportDeleteSynonymRuleAction extends HandledTransportAction<Del
|
||||||
synonymsManagementAPIService.deleteSynonymRule(
|
synonymsManagementAPIService.deleteSynonymRule(
|
||||||
request.synonymsSetId(),
|
request.synonymsSetId(),
|
||||||
request.synonymRuleId(),
|
request.synonymRuleId(),
|
||||||
|
request.refresh(),
|
||||||
listener.map(SynonymUpdateResponse::new)
|
listener.map(SynonymUpdateResponse::new)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,8 @@ public class TransportPutSynonymRuleAction extends HandledTransportAction<PutSyn
|
||||||
synonymsManagementAPIService.putSynonymRule(
|
synonymsManagementAPIService.putSynonymRule(
|
||||||
request.synonymsSetId(),
|
request.synonymsSetId(),
|
||||||
request.synonymRule(),
|
request.synonymRule(),
|
||||||
listener.map(updateResponse -> new SynonymUpdateResponse(updateResponse))
|
request.refresh(),
|
||||||
|
listener.map(SynonymUpdateResponse::new)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class TransportPutSynonymsAction extends HandledTransportAction<PutSynony
|
||||||
synonymsManagementAPIService.putSynonymsSet(
|
synonymsManagementAPIService.putSynonymsSet(
|
||||||
request.synonymsSetId(),
|
request.synonymsSetId(),
|
||||||
request.synonymRules(),
|
request.synonymRules(),
|
||||||
|
request.refresh(),
|
||||||
listener.map(SynonymUpdateResponse::new)
|
listener.map(SynonymUpdateResponse::new)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
|
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
|
||||||
|
|
||||||
|
@ -39,8 +40,14 @@ public class RestDeleteSynonymRuleAction extends BaseRestHandler {
|
||||||
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
|
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
|
||||||
DeleteSynonymRuleAction.Request request = new DeleteSynonymRuleAction.Request(
|
DeleteSynonymRuleAction.Request request = new DeleteSynonymRuleAction.Request(
|
||||||
restRequest.param("synonymsSet"),
|
restRequest.param("synonymsSet"),
|
||||||
restRequest.param("synonymRuleId")
|
restRequest.param("synonymRuleId"),
|
||||||
|
restRequest.paramAsBoolean("refresh", true)
|
||||||
);
|
);
|
||||||
return channel -> client.execute(DeleteSynonymRuleAction.INSTANCE, request, new RestToXContentListener<>(channel));
|
return channel -> client.execute(DeleteSynonymRuleAction.INSTANCE, request, new RestToXContentListener<>(channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> supportedCapabilities() {
|
||||||
|
return SynonymCapabilities.CAPABILITIES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ public class RestPutSynonymRuleAction extends BaseRestHandler {
|
||||||
PutSynonymRuleAction.Request request = new PutSynonymRuleAction.Request(
|
PutSynonymRuleAction.Request request = new PutSynonymRuleAction.Request(
|
||||||
restRequest.param("synonymsSet"),
|
restRequest.param("synonymsSet"),
|
||||||
restRequest.param("synonymRuleId"),
|
restRequest.param("synonymRuleId"),
|
||||||
|
restRequest.paramAsBoolean("refresh", true),
|
||||||
restRequest.content(),
|
restRequest.content(),
|
||||||
restRequest.getXContentType()
|
restRequest.getXContentType()
|
||||||
);
|
);
|
||||||
|
@ -50,4 +52,9 @@ public class RestPutSynonymRuleAction extends BaseRestHandler {
|
||||||
new RestToXContentListener<>(channel, SynonymUpdateResponse::status, r -> null)
|
new RestToXContentListener<>(channel, SynonymUpdateResponse::status, r -> null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> supportedCapabilities() {
|
||||||
|
return SynonymCapabilities.CAPABILITIES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ public class RestPutSynonymsAction extends BaseRestHandler {
|
||||||
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
|
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
|
||||||
PutSynonymsAction.Request request = new PutSynonymsAction.Request(
|
PutSynonymsAction.Request request = new PutSynonymsAction.Request(
|
||||||
restRequest.param("synonymsSet"),
|
restRequest.param("synonymsSet"),
|
||||||
|
restRequest.paramAsBoolean("refresh", true),
|
||||||
restRequest.content(),
|
restRequest.content(),
|
||||||
restRequest.getXContentType()
|
restRequest.getXContentType()
|
||||||
);
|
);
|
||||||
|
@ -49,4 +51,9 @@ public class RestPutSynonymsAction extends BaseRestHandler {
|
||||||
new RestToXContentListener<>(channel, SynonymUpdateResponse::status, r -> null)
|
new RestToXContentListener<>(channel, SynonymUpdateResponse::status, r -> null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> supportedCapabilities() {
|
||||||
|
return SynonymCapabilities.CAPABILITIES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.rest.action.synonyms;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Set} of "capabilities" supported by the {@link RestPutSynonymsAction} and {@link RestPutSynonymRuleAction}.
|
||||||
|
*/
|
||||||
|
public final class SynonymCapabilities {
|
||||||
|
|
||||||
|
private SynonymCapabilities() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String SYNONYMS_REFRESH_PARAM = "synonyms_refresh_param";
|
||||||
|
|
||||||
|
public static final Set<String> CAPABILITIES = Set.of(SYNONYMS_REFRESH_PARAM);
|
||||||
|
}
|
|
@ -19,6 +19,9 @@ import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.DelegatingActionListener;
|
import org.elasticsearch.action.DelegatingActionListener;
|
||||||
import org.elasticsearch.action.DocWriteRequest;
|
import org.elasticsearch.action.DocWriteRequest;
|
||||||
import org.elasticsearch.action.DocWriteResponse;
|
import org.elasticsearch.action.DocWriteResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.TransportClusterHealthAction;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersRequest;
|
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersRequest;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.TransportReloadAnalyzersAction;
|
import org.elasticsearch.action.admin.indices.analyze.TransportReloadAnalyzersAction;
|
||||||
|
@ -36,12 +39,14 @@ import org.elasticsearch.client.internal.OriginSettingClient;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||||
import org.elasticsearch.cluster.routing.Preference;
|
import org.elasticsearch.cluster.routing.Preference;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.core.TimeValue;
|
||||||
import org.elasticsearch.index.IndexNotFoundException;
|
import org.elasticsearch.index.IndexNotFoundException;
|
||||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||||
import org.elasticsearch.index.query.QueryBuilders;
|
import org.elasticsearch.index.query.QueryBuilders;
|
||||||
import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
import org.elasticsearch.index.reindex.BulkByScrollResponse;
|
||||||
import org.elasticsearch.index.reindex.DeleteByQueryAction;
|
import org.elasticsearch.index.reindex.DeleteByQueryAction;
|
||||||
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
|
||||||
|
import org.elasticsearch.indices.IndexCreationException;
|
||||||
import org.elasticsearch.indices.SystemIndexDescriptor;
|
import org.elasticsearch.indices.SystemIndexDescriptor;
|
||||||
import org.elasticsearch.rest.RestStatus;
|
import org.elasticsearch.rest.RestStatus;
|
||||||
import org.elasticsearch.search.aggregations.BucketOrder;
|
import org.elasticsearch.search.aggregations.BucketOrder;
|
||||||
|
@ -72,7 +77,7 @@ public class SynonymsManagementAPIService {
|
||||||
|
|
||||||
private static final String SYNONYMS_INDEX_NAME_PATTERN = ".synonyms-*";
|
private static final String SYNONYMS_INDEX_NAME_PATTERN = ".synonyms-*";
|
||||||
private static final int SYNONYMS_INDEX_FORMAT = 2;
|
private static final int SYNONYMS_INDEX_FORMAT = 2;
|
||||||
private static final String SYNONYMS_INDEX_CONCRETE_NAME = ".synonyms-" + SYNONYMS_INDEX_FORMAT;
|
static final String SYNONYMS_INDEX_CONCRETE_NAME = ".synonyms-" + SYNONYMS_INDEX_FORMAT;
|
||||||
private static final String SYNONYMS_ALIAS_NAME = ".synonyms";
|
private static final String SYNONYMS_ALIAS_NAME = ".synonyms";
|
||||||
public static final String SYNONYMS_FEATURE_NAME = "synonyms";
|
public static final String SYNONYMS_FEATURE_NAME = "synonyms";
|
||||||
// Stores the synonym set the rule belongs to
|
// Stores the synonym set the rule belongs to
|
||||||
|
@ -90,6 +95,7 @@ public class SynonymsManagementAPIService {
|
||||||
private static final String SYNONYM_RULE_ID_FIELD = SynonymRule.ID_FIELD.getPreferredName();
|
private static final String SYNONYM_RULE_ID_FIELD = SynonymRule.ID_FIELD.getPreferredName();
|
||||||
private static final String SYNONYM_SETS_AGG_NAME = "synonym_sets_aggr";
|
private static final String SYNONYM_SETS_AGG_NAME = "synonym_sets_aggr";
|
||||||
private static final int SYNONYMS_INDEX_MAPPINGS_VERSION = 1;
|
private static final int SYNONYMS_INDEX_MAPPINGS_VERSION = 1;
|
||||||
|
public static final int INDEX_SEARCHABLE_TIMEOUT_SECONDS = 30;
|
||||||
private final int maxSynonymsSets;
|
private final int maxSynonymsSets;
|
||||||
|
|
||||||
// Package private for testing
|
// Package private for testing
|
||||||
|
@ -301,7 +307,12 @@ public class SynonymsManagementAPIService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putSynonymsSet(String synonymSetId, SynonymRule[] synonymsSet, ActionListener<SynonymsReloadResult> listener) {
|
public void putSynonymsSet(
|
||||||
|
String synonymSetId,
|
||||||
|
SynonymRule[] synonymsSet,
|
||||||
|
boolean refresh,
|
||||||
|
ActionListener<SynonymsReloadResult> listener
|
||||||
|
) {
|
||||||
if (synonymsSet.length > maxSynonymsSets) {
|
if (synonymsSet.length > maxSynonymsSets) {
|
||||||
listener.onFailure(
|
listener.onFailure(
|
||||||
new IllegalArgumentException("The number of synonyms rules in a synonym set cannot exceed " + maxSynonymsSets)
|
new IllegalArgumentException("The number of synonyms rules in a synonym set cannot exceed " + maxSynonymsSets)
|
||||||
|
@ -343,7 +354,13 @@ public class SynonymsManagementAPIService {
|
||||||
? UpdateSynonymsResultStatus.CREATED
|
? UpdateSynonymsResultStatus.CREATED
|
||||||
: UpdateSynonymsResultStatus.UPDATED;
|
: UpdateSynonymsResultStatus.UPDATED;
|
||||||
|
|
||||||
reloadAnalyzers(synonymSetId, false, bulkInsertResponseListener, updateSynonymsResultStatus);
|
checkIndexSearchableAndReloadAnalyzers(
|
||||||
|
synonymSetId,
|
||||||
|
refresh,
|
||||||
|
false,
|
||||||
|
updateSynonymsResultStatus,
|
||||||
|
bulkInsertResponseListener
|
||||||
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
|
@ -366,7 +383,12 @@ public class SynonymsManagementAPIService {
|
||||||
bulkRequestBuilder.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).execute(listener);
|
bulkRequestBuilder.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).execute(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putSynonymRule(String synonymsSetId, SynonymRule synonymRule, ActionListener<SynonymsReloadResult> listener) {
|
public void putSynonymRule(
|
||||||
|
String synonymsSetId,
|
||||||
|
SynonymRule synonymRule,
|
||||||
|
boolean refresh,
|
||||||
|
ActionListener<SynonymsReloadResult> listener
|
||||||
|
) {
|
||||||
checkSynonymSetExists(synonymsSetId, listener.delegateFailureAndWrap((l1, obj) -> {
|
checkSynonymSetExists(synonymsSetId, listener.delegateFailureAndWrap((l1, obj) -> {
|
||||||
// Count synonym rules to check if we're at maximum
|
// Count synonym rules to check if we're at maximum
|
||||||
BoolQueryBuilder queryFilter = QueryBuilders.boolQuery()
|
BoolQueryBuilder queryFilter = QueryBuilders.boolQuery()
|
||||||
|
@ -388,14 +410,18 @@ public class SynonymsManagementAPIService {
|
||||||
new IllegalArgumentException("The number of synonym rules in a synonyms set cannot exceed " + maxSynonymsSets)
|
new IllegalArgumentException("The number of synonym rules in a synonyms set cannot exceed " + maxSynonymsSets)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
indexSynonymRule(synonymsSetId, synonymRule, searchListener);
|
indexSynonymRule(synonymsSetId, synonymRule, refresh, searchListener);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void indexSynonymRule(String synonymsSetId, SynonymRule synonymRule, ActionListener<SynonymsReloadResult> listener)
|
private void indexSynonymRule(
|
||||||
throws IOException {
|
String synonymsSetId,
|
||||||
|
SynonymRule synonymRule,
|
||||||
|
boolean refresh,
|
||||||
|
ActionListener<SynonymsReloadResult> listener
|
||||||
|
) throws IOException {
|
||||||
IndexRequest indexRequest = createSynonymRuleIndexRequest(synonymsSetId, synonymRule).setRefreshPolicy(
|
IndexRequest indexRequest = createSynonymRuleIndexRequest(synonymsSetId, synonymRule).setRefreshPolicy(
|
||||||
WriteRequest.RefreshPolicy.IMMEDIATE
|
WriteRequest.RefreshPolicy.IMMEDIATE
|
||||||
);
|
);
|
||||||
|
@ -404,7 +430,7 @@ public class SynonymsManagementAPIService {
|
||||||
? UpdateSynonymsResultStatus.CREATED
|
? UpdateSynonymsResultStatus.CREATED
|
||||||
: UpdateSynonymsResultStatus.UPDATED;
|
: UpdateSynonymsResultStatus.UPDATED;
|
||||||
|
|
||||||
reloadAnalyzers(synonymsSetId, false, l2, updateStatus);
|
checkIndexSearchableAndReloadAnalyzers(synonymsSetId, refresh, false, updateStatus, l2);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +450,12 @@ public class SynonymsManagementAPIService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteSynonymRule(String synonymsSetId, String synonymRuleId, ActionListener<SynonymsReloadResult> listener) {
|
public void deleteSynonymRule(
|
||||||
|
String synonymsSetId,
|
||||||
|
String synonymRuleId,
|
||||||
|
boolean refresh,
|
||||||
|
ActionListener<SynonymsReloadResult> listener
|
||||||
|
) {
|
||||||
client.prepareDelete(SYNONYMS_ALIAS_NAME, internalSynonymRuleId(synonymsSetId, synonymRuleId))
|
client.prepareDelete(SYNONYMS_ALIAS_NAME, internalSynonymRuleId(synonymsSetId, synonymRuleId))
|
||||||
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE)
|
||||||
.execute(new DelegatingIndexNotFoundActionListener<>(synonymsSetId, listener, (l, deleteResponse) -> {
|
.execute(new DelegatingIndexNotFoundActionListener<>(synonymsSetId, listener, (l, deleteResponse) -> {
|
||||||
|
@ -443,7 +474,11 @@ public class SynonymsManagementAPIService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadAnalyzers(synonymsSetId, false, listener, UpdateSynonymsResultStatus.DELETED);
|
if (refresh) {
|
||||||
|
reloadAnalyzers(synonymsSetId, false, UpdateSynonymsResultStatus.DELETED, listener);
|
||||||
|
} else {
|
||||||
|
listener.onResponse(new SynonymsReloadResult(UpdateSynonymsResultStatus.DELETED, null));
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +536,7 @@ public class SynonymsManagementAPIService {
|
||||||
public void deleteSynonymsSet(String synonymSetId, ActionListener<AcknowledgedResponse> listener) {
|
public void deleteSynonymsSet(String synonymSetId, ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
|
||||||
// Previews reloading the resource to understand its usage on indices
|
// Previews reloading the resource to understand its usage on indices
|
||||||
reloadAnalyzers(synonymSetId, true, listener.delegateFailure((reloadListener, reloadResult) -> {
|
reloadAnalyzers(synonymSetId, true, null, listener.delegateFailure((reloadListener, reloadResult) -> {
|
||||||
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadDetails = reloadResult.reloadAnalyzersResponse.getReloadDetails();
|
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadDetails = reloadResult.reloadAnalyzersResponse.getReloadDetails();
|
||||||
if (reloadDetails.isEmpty() == false) {
|
if (reloadDetails.isEmpty() == false) {
|
||||||
Set<String> indices = reloadDetails.entrySet()
|
Set<String> indices = reloadDetails.entrySet()
|
||||||
|
@ -538,14 +573,48 @@ public class SynonymsManagementAPIService {
|
||||||
|
|
||||||
deleteObjectsListener.onResponse(AcknowledgedResponse.of(true));
|
deleteObjectsListener.onResponse(AcknowledgedResponse.of(true));
|
||||||
}));
|
}));
|
||||||
}), null);
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void reloadAnalyzers(
|
private <T> void checkIndexSearchableAndReloadAnalyzers(
|
||||||
|
String synonymSetId,
|
||||||
|
boolean refresh,
|
||||||
|
boolean preview,
|
||||||
|
UpdateSynonymsResultStatus synonymsOperationResult,
|
||||||
|
ActionListener<SynonymsReloadResult> listener
|
||||||
|
) {
|
||||||
|
|
||||||
|
if (refresh == false) {
|
||||||
|
// If not refreshing, we don't need to reload analyzers
|
||||||
|
listener.onResponse(new SynonymsReloadResult(synonymsOperationResult, null));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check synonyms index is searchable before reloading, to ensure analyzers are able to load the changed information
|
||||||
|
checkSynonymsIndexHealth(listener.delegateFailure((l, response) -> {
|
||||||
|
if (response.isTimedOut()) {
|
||||||
|
l.onFailure(
|
||||||
|
new IndexCreationException(
|
||||||
|
"synonyms index ["
|
||||||
|
+ SYNONYMS_ALIAS_NAME
|
||||||
|
+ "] is not searchable. "
|
||||||
|
+ response.getActiveShardsPercent()
|
||||||
|
+ "% shards are active",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadAnalyzers(synonymSetId, preview, synonymsOperationResult, listener);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadAnalyzers(
|
||||||
String synonymSetId,
|
String synonymSetId,
|
||||||
boolean preview,
|
boolean preview,
|
||||||
ActionListener<SynonymsReloadResult> listener,
|
UpdateSynonymsResultStatus synonymsOperationResult,
|
||||||
UpdateSynonymsResultStatus synonymsOperationResult
|
ActionListener<SynonymsReloadResult> listener
|
||||||
) {
|
) {
|
||||||
// auto-reload all reloadable analyzers (currently only those that use updateable synonym or keyword_marker filters)
|
// auto-reload all reloadable analyzers (currently only those that use updateable synonym or keyword_marker filters)
|
||||||
ReloadAnalyzersRequest reloadAnalyzersRequest = new ReloadAnalyzersRequest(synonymSetId, preview, "*");
|
ReloadAnalyzersRequest reloadAnalyzersRequest = new ReloadAnalyzersRequest(synonymSetId, preview, "*");
|
||||||
|
@ -556,13 +625,23 @@ public class SynonymsManagementAPIService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allows checking failures in tests
|
||||||
|
void checkSynonymsIndexHealth(ActionListener<ClusterHealthResponse> listener) {
|
||||||
|
ClusterHealthRequest healthRequest = new ClusterHealthRequest(
|
||||||
|
TimeValue.timeValueSeconds(INDEX_SEARCHABLE_TIMEOUT_SECONDS),
|
||||||
|
SYNONYMS_ALIAS_NAME
|
||||||
|
).waitForGreenStatus();
|
||||||
|
|
||||||
|
client.execute(TransportClusterHealthAction.TYPE, healthRequest, listener);
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieves the internal synonym rule ID to store it in the index. As the same synonym rule ID
|
// Retrieves the internal synonym rule ID to store it in the index. As the same synonym rule ID
|
||||||
// can be used in different synonym sets, we prefix the ID with the synonym set to avoid collisions
|
// can be used in different synonym sets, we prefix the ID with the synonym set to avoid collisions
|
||||||
private static String internalSynonymRuleId(String synonymsSetId, String synonymRuleId) {
|
private static String internalSynonymRuleId(String synonymsSetId, String synonymRuleId) {
|
||||||
return synonymsSetId + SYNONYM_RULE_ID_SEPARATOR + synonymRuleId;
|
return synonymsSetId + SYNONYM_RULE_ID_SEPARATOR + synonymRuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Settings settings() {
|
private static Settings settings() {
|
||||||
return Settings.builder()
|
return Settings.builder()
|
||||||
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
|
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, 1)
|
||||||
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1")
|
.put(IndexMetadata.SETTING_AUTO_EXPAND_REPLICAS, "0-1")
|
||||||
|
|
|
@ -31,7 +31,7 @@ import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg
|
||||||
public class ReloadAnalyzersResponseTests extends AbstractBroadcastResponseTestCase<ReloadAnalyzersResponse> {
|
public class ReloadAnalyzersResponseTests extends AbstractBroadcastResponseTestCase<ReloadAnalyzersResponse> {
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
private static final ConstructingObjectParser<ReloadAnalyzersResponse, Void> PARSER = new ConstructingObjectParser<>(
|
public static final ConstructingObjectParser<ReloadAnalyzersResponse, Void> PARSER = new ConstructingObjectParser<>(
|
||||||
"reload_analyzer",
|
"reload_analyzer",
|
||||||
true,
|
true,
|
||||||
arg -> {
|
arg -> {
|
||||||
|
@ -67,8 +67,8 @@ public class ReloadAnalyzersResponseTests extends AbstractBroadcastResponseTestC
|
||||||
declareBroadcastFields(PARSER);
|
declareBroadcastFields(PARSER);
|
||||||
PARSER.declareObjectArray(constructorArg(), ENTRY_PARSER, ReloadAnalyzersResponse.RELOAD_DETAILS_FIELD);
|
PARSER.declareObjectArray(constructorArg(), ENTRY_PARSER, ReloadAnalyzersResponse.RELOAD_DETAILS_FIELD);
|
||||||
ENTRY_PARSER.declareString(constructorArg(), ReloadAnalyzersResponse.INDEX_FIELD);
|
ENTRY_PARSER.declareString(constructorArg(), ReloadAnalyzersResponse.INDEX_FIELD);
|
||||||
ENTRY_PARSER.declareStringArray(constructorArg(), ReloadAnalyzersResponse.RELOADED_ANALYZERS_FIELD);
|
|
||||||
ENTRY_PARSER.declareStringArray(constructorArg(), ReloadAnalyzersResponse.RELOADED_NODE_IDS_FIELD);
|
ENTRY_PARSER.declareStringArray(constructorArg(), ReloadAnalyzersResponse.RELOADED_NODE_IDS_FIELD);
|
||||||
|
ENTRY_PARSER.declareStringArray(constructorArg(), ReloadAnalyzersResponse.RELOADED_ANALYZERS_FIELD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class DeleteSynonymRuleActionRequestSerializingTests extends AbstractWire
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DeleteSynonymRuleAction.Request createTestInstance() {
|
protected DeleteSynonymRuleAction.Request createTestInstance() {
|
||||||
return new DeleteSynonymRuleAction.Request(randomIdentifier(), randomIdentifier());
|
return new DeleteSynonymRuleAction.Request(randomIdentifier(), randomIdentifier(), randomBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -22,7 +22,7 @@ public class PutSynonymRuleActionRequestSerializingTests extends AbstractWireSer
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PutSynonymRuleAction.Request createTestInstance() {
|
protected PutSynonymRuleAction.Request createTestInstance() {
|
||||||
return new PutSynonymRuleAction.Request(randomIdentifier(), SynonymsTestUtils.randomSynonymRule());
|
return new PutSynonymRuleAction.Request(randomIdentifier(), SynonymsTestUtils.randomSynonymRule(), randomBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,7 @@ public class PutSynonymsActionRequestSerializingTests extends AbstractWireSerial
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PutSynonymsAction.Request createTestInstance() {
|
protected PutSynonymsAction.Request createTestInstance() {
|
||||||
return new PutSynonymsAction.Request(randomIdentifier(), randomSynonymsSet());
|
return new PutSynonymsAction.Request(randomIdentifier(), randomSynonymsSet(), randomBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,23 +9,54 @@
|
||||||
|
|
||||||
package org.elasticsearch.action.synonyms;
|
package org.elasticsearch.action.synonyms;
|
||||||
|
|
||||||
|
import org.elasticsearch.TransportVersion;
|
||||||
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponse;
|
||||||
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponseTests;
|
import org.elasticsearch.action.admin.indices.analyze.ReloadAnalyzersResponseTests;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.io.stream.Writeable;
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||||
|
import org.elasticsearch.synonyms.SynonymsManagementAPIService;
|
||||||
import org.elasticsearch.synonyms.SynonymsManagementAPIService.SynonymsReloadResult;
|
import org.elasticsearch.synonyms.SynonymsManagementAPIService.SynonymsReloadResult;
|
||||||
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
import org.elasticsearch.test.AbstractBWCSerializationTestCase;
|
||||||
|
import org.elasticsearch.xcontent.ConstructingObjectParser;
|
||||||
|
import org.elasticsearch.xcontent.ParseField;
|
||||||
|
import org.elasticsearch.xcontent.XContentParser;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.elasticsearch.action.synonyms.SynonymUpdateResponse.EMPTY_RELOAD_ANALYZER_RESPONSE;
|
||||||
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.CREATED;
|
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.CREATED;
|
||||||
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.DELETED;
|
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.DELETED;
|
||||||
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.UPDATED;
|
import static org.elasticsearch.synonyms.SynonymsManagementAPIService.UpdateSynonymsResultStatus.UPDATED;
|
||||||
|
import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
|
||||||
|
import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
||||||
|
|
||||||
public class SynonymUpdateResponseSerializingTests extends AbstractWireSerializingTestCase<SynonymUpdateResponse> {
|
public class SynonymUpdateResponseSerializingTests extends AbstractBWCSerializationTestCase<SynonymUpdateResponse> {
|
||||||
|
|
||||||
|
private static final ConstructingObjectParser<SynonymUpdateResponse, Void> PARSER = new ConstructingObjectParser<>(
|
||||||
|
"synonyms_update_response",
|
||||||
|
true,
|
||||||
|
arg -> {
|
||||||
|
SynonymsManagementAPIService.UpdateSynonymsResultStatus status = SynonymsManagementAPIService.UpdateSynonymsResultStatus
|
||||||
|
.valueOf(((String) arg[0]).toUpperCase(Locale.ROOT));
|
||||||
|
ReloadAnalyzersResponse reloadAnalyzersResponse = (ReloadAnalyzersResponse) arg[1];
|
||||||
|
return new SynonymUpdateResponse(new SynonymsReloadResult(status, reloadAnalyzersResponse));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
static {
|
||||||
|
PARSER.declareString(constructorArg(), new ParseField(SynonymUpdateResponse.RESULT_FIELD));
|
||||||
|
PARSER.declareObjectOrNull(
|
||||||
|
optionalConstructorArg(),
|
||||||
|
(p, c) -> ReloadAnalyzersResponseTests.PARSER.parse(p, null),
|
||||||
|
null,
|
||||||
|
new ParseField(SynonymUpdateResponse.RELOAD_ANALYZERS_DETAILS_FIELD)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Writeable.Reader<SynonymUpdateResponse> instanceReader() {
|
protected Writeable.Reader<SynonymUpdateResponse> instanceReader() {
|
||||||
|
@ -34,9 +65,22 @@ public class SynonymUpdateResponseSerializingTests extends AbstractWireSerializi
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SynonymUpdateResponse createTestInstance() {
|
protected SynonymUpdateResponse createTestInstance() {
|
||||||
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadedIndicesDetails = ReloadAnalyzersResponseTests
|
return createTestInstance(randomBoolean());
|
||||||
.createRandomReloadDetails();
|
}
|
||||||
ReloadAnalyzersResponse reloadAnalyzersResponse = new ReloadAnalyzersResponse(10, 10, 0, null, reloadedIndicesDetails);
|
|
||||||
|
private SynonymUpdateResponse createTestInstance(boolean includeReloadInfo) {
|
||||||
|
ReloadAnalyzersResponse reloadAnalyzersResponse = null;
|
||||||
|
if (includeReloadInfo) {
|
||||||
|
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadedIndicesDetails = ReloadAnalyzersResponseTests
|
||||||
|
.createRandomReloadDetails();
|
||||||
|
reloadAnalyzersResponse = new ReloadAnalyzersResponse(
|
||||||
|
randomIntBetween(0, 10),
|
||||||
|
randomIntBetween(0, 10),
|
||||||
|
randomIntBetween(0, 5),
|
||||||
|
null,
|
||||||
|
reloadedIndicesDetails
|
||||||
|
);
|
||||||
|
}
|
||||||
return new SynonymUpdateResponse(new SynonymsReloadResult(randomFrom(CREATED, UPDATED, DELETED), reloadAnalyzersResponse));
|
return new SynonymUpdateResponse(new SynonymsReloadResult(randomFrom(CREATED, UPDATED, DELETED), reloadAnalyzersResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +89,17 @@ public class SynonymUpdateResponseSerializingTests extends AbstractWireSerializi
|
||||||
return randomValueOtherThan(instance, this::createTestInstance);
|
return randomValueOtherThan(instance, this::createTestInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SynonymUpdateResponse mutateInstanceForVersion(SynonymUpdateResponse instance, TransportVersion version) {
|
||||||
|
|
||||||
|
if (version.before(TransportVersions.SYNONYMS_REFRESH_PARAM) && instance.reloadAnalyzersResponse() == null) {
|
||||||
|
// Nulls will be written as empty reload analyzer responses for older versions
|
||||||
|
return new SynonymUpdateResponse(new SynonymsReloadResult(instance.updateStatus(), EMPTY_RELOAD_ANALYZER_RESPONSE));
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
public void testToXContent() throws IOException {
|
public void testToXContent() throws IOException {
|
||||||
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadedIndicesNodes = Collections.singletonMap(
|
Map<String, ReloadAnalyzersResponse.ReloadDetails> reloadedIndicesNodes = Collections.singletonMap(
|
||||||
"index",
|
"index",
|
||||||
|
@ -73,4 +128,18 @@ public class SynonymUpdateResponseSerializingTests extends AbstractWireSerializi
|
||||||
}
|
}
|
||||||
}"""), output);
|
}"""), output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testToXContentWithNoReloadResult() throws IOException {
|
||||||
|
SynonymUpdateResponse response = new SynonymUpdateResponse(new SynonymsReloadResult(CREATED, null));
|
||||||
|
String output = Strings.toString(response);
|
||||||
|
assertEquals(XContentHelper.stripWhitespace("""
|
||||||
|
{
|
||||||
|
"result": "created"
|
||||||
|
}"""), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SynonymUpdateResponse doParseInstance(XContentParser parser) throws IOException {
|
||||||
|
return PARSER.apply(parser, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,7 +282,7 @@ public class InternalUsers {
|
||||||
UsernamesField.SYNONYMS_USER_NAME,
|
UsernamesField.SYNONYMS_USER_NAME,
|
||||||
new RoleDescriptor(
|
new RoleDescriptor(
|
||||||
UsernamesField.SYNONYMS_ROLE_NAME,
|
UsernamesField.SYNONYMS_ROLE_NAME,
|
||||||
null,
|
new String[] { "monitor" },
|
||||||
new RoleDescriptor.IndicesPrivileges[] {
|
new RoleDescriptor.IndicesPrivileges[] {
|
||||||
RoleDescriptor.IndicesPrivileges.builder().indices(".synonyms*").privileges("all").allowRestrictedIndices(true).build(),
|
RoleDescriptor.IndicesPrivileges.builder().indices(".synonyms*").privileges("all").allowRestrictedIndices(true).build(),
|
||||||
RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges(TransportReloadAnalyzersAction.TYPE.name()).build(), },
|
RoleDescriptor.IndicesPrivileges.builder().indices("*").privileges(TransportReloadAnalyzersAction.TYPE.name()).build(), },
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue