Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.

Commit a095266

Browse files
setiahdbbaughe
andauthored
Adds support for dynamically updatable search analyzers (#290)
* Squashed commit of the following: commit c8c8233 Author: Himanshu Setia <[email protected]> Date: Tue Sep 8 19:21:58 2020 -0700 removing comments, linting changes commit 52526e8 Author: Himanshu Setia <[email protected]> Date: Tue Sep 8 19:09:30 2020 -0700 Making refresh_synonym_analyzer uri odfe compatible commit d4cc71e Author: Himanshu Setia <[email protected]> Date: Tue Sep 8 18:33:39 2020 -0700 Adding copyright disclaimer to new files commit 9af7fdf Author: Himanshu Setia <[email protected]> Date: Tue Sep 8 17:26:53 2020 -0700 Misc - removing comments, adding newline, etc. commit 1c85f18 Author: Himanshu Setia <[email protected]> Date: Tue Sep 8 16:39:26 2020 -0700 Adding _refresh_synonym_analyzer API to support dynamic update for search analyzers * Refactoring - API renaming * Response parsing changes * Fixed multinode response parsing issue * Refactoring and logging * Fixing klint errors * Adding UTs to validate stream parsing * CR comments, code refactoring and more UTs Squashed commit of the following: commit d87842e4ccb592a39d6b6897a2b9cde9ddc2839f Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 23:36:24 2020 -0700 Reverting RefreshSearchAnalyzerResponse stream input output parsing test for fixing later commit 33ef3223acde38a64575255f7ec702f807d0502e Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 23:34:49 2020 -0700 Fixing missing indices test commit 8516d2142362c61630682bf7353e019bf9f6a9eb Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 21:59:55 2020 -0700 CR comments and added more UTs commit d306421ca462f2614756a73231baeeb56b388365 Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 20:15:59 2020 -0700 shardFailure refactoring commit da80de7a68fef05e524e624ea1a8da6afdbf11d4 Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 18:14:45 2020 -0700 Working changes after refactoring shardFailure commit be9bf2daaa31fb6444f799a8f3ed3d0383551471 Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 17:45:31 2020 -0700 Corrected response parsing for indices with some failed shards commit 256f06ed23ac4ab2d78724601a1dd7e9d1423331 Author: Himanshu Setia <[email protected]> Date: Thu Sep 10 17:12:00 2020 -0700 Working * Integ test fixes by enforcing refresh during ingestion * CR comments - reading shardResponses as List from inputStream * API path change and few minor tweaks * misc changes * Reverting action name to follow the code convention Co-authored-by: Drew Baugher <[email protected]>
1 parent 1042dd6 commit a095266

14 files changed

+852
-8
lines changed

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ integTest.runner {
180180
systemProperty 'tests.security.manager', 'false'
181181
systemProperty 'java.io.tmpdir', es_tmp_dir.absolutePath
182182
systemProperty 'tests.path.repo', repo.absolutePath
183+
systemProperty 'buildDir', buildDir
183184
// Tell the test JVM if the cluster JVM is running under a debugger so that tests can use longer timeouts for
184185
// requests. The 'doFirst' delays reading the debug setting on the cluster till execution time.
185186
doFirst {

src/main/kotlin/com/amazon/opendistroforelasticsearch/indexmanagement/IndexManagementPlugin.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ import com.amazon.opendistroforelasticsearch.indexmanagement.indexstatemanagemen
3131
import com.amazon.opendistroforelasticsearch.indexmanagement.indexstatemanagement.resthandler.RestRemovePolicyAction
3232
import com.amazon.opendistroforelasticsearch.indexmanagement.indexstatemanagement.resthandler.RestRetryFailedManagedIndexAction
3333
import com.amazon.opendistroforelasticsearch.indexmanagement.indexstatemanagement.settings.ManagedIndexSettings
34+
import com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer.RefreshSearchAnalyzerAction
35+
import com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer.RestRefreshSearchAnalyzerAction
36+
import com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer.TransportRefreshSearchAnalyzerAction
3437
import com.amazon.opendistroforelasticsearch.jobscheduler.spi.JobSchedulerExtension
3538
import com.amazon.opendistroforelasticsearch.jobscheduler.spi.ScheduledJobParser
3639
import com.amazon.opendistroforelasticsearch.jobscheduler.spi.ScheduledJobRunner
@@ -117,6 +120,7 @@ internal class IndexManagementPlugin : JobSchedulerExtension, ActionPlugin, Plug
117120
nodesInCluster: Supplier<DiscoveryNodes>
118121
): List<RestHandler> {
119122
return listOf(
123+
RestRefreshSearchAnalyzerAction(),
120124
RestIndexPolicyAction(settings, clusterService, indexManagementIndices),
121125
RestGetPolicyAction(),
122126
RestDeletePolicyAction(),
@@ -190,6 +194,10 @@ internal class IndexManagementPlugin : JobSchedulerExtension, ActionPlugin, Plug
190194
ActionPlugin.ActionHandler(
191195
UpdateManagedIndexMetaDataAction.INSTANCE,
192196
TransportUpdateManagedIndexMetaDataAction::class.java
197+
),
198+
ActionPlugin.ActionHandler(
199+
RefreshSearchAnalyzerAction.INSTANCE,
200+
TransportRefreshSearchAnalyzerAction::class.java
193201
)
194202
)
195203
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer
17+
18+
import org.elasticsearch.action.ActionType
19+
import org.elasticsearch.common.io.stream.Writeable
20+
21+
class RefreshSearchAnalyzerAction : ActionType<RefreshSearchAnalyzerResponse>(NAME, reader) {
22+
companion object {
23+
const val NAME = "indices:admin/refresh_search_analyzers"
24+
val INSTANCE = RefreshSearchAnalyzerAction()
25+
val reader = Writeable.Reader { inp -> RefreshSearchAnalyzerResponse(inp) }
26+
}
27+
28+
override fun getResponseReader(): Writeable.Reader<RefreshSearchAnalyzerResponse> = reader
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer
17+
18+
import org.elasticsearch.action.support.broadcast.BroadcastRequest
19+
import org.elasticsearch.common.io.stream.StreamInput
20+
import java.io.IOException
21+
22+
class RefreshSearchAnalyzerRequest : BroadcastRequest<RefreshSearchAnalyzerRequest> {
23+
constructor(vararg indices: String) : super(*indices)
24+
25+
@Throws(IOException::class)
26+
constructor(inp: StreamInput) : super(inp)
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer
17+
18+
import org.elasticsearch.action.support.DefaultShardOperationFailedException
19+
import org.elasticsearch.action.support.broadcast.BroadcastResponse
20+
import org.elasticsearch.common.io.stream.StreamInput
21+
import org.elasticsearch.common.io.stream.StreamOutput
22+
import org.elasticsearch.common.xcontent.ConstructingObjectParser
23+
import org.elasticsearch.common.xcontent.ToXContent.Params
24+
import org.elasticsearch.common.xcontent.XContentBuilder
25+
import org.elasticsearch.rest.action.RestActions
26+
import java.io.IOException
27+
import java.util.function.Function
28+
29+
class RefreshSearchAnalyzerResponse : BroadcastResponse {
30+
31+
private lateinit var shardResponses: MutableList<RefreshSearchAnalyzerShardResponse>
32+
private lateinit var shardFailures: MutableList<DefaultShardOperationFailedException>
33+
34+
@Throws(IOException::class)
35+
constructor(inp: StreamInput) : super(inp) {
36+
inp.readList(::RefreshSearchAnalyzerShardResponse)
37+
inp.readList(DefaultShardOperationFailedException::readShardOperationFailed)
38+
}
39+
40+
constructor(
41+
totalShards: Int,
42+
successfulShards: Int,
43+
failedShards: Int,
44+
shardFailures: List<DefaultShardOperationFailedException>,
45+
shardResponses: List<RefreshSearchAnalyzerShardResponse>
46+
) : super(
47+
totalShards, successfulShards, failedShards, shardFailures
48+
) {
49+
this.shardResponses = shardResponses.toMutableList()
50+
this.shardFailures = shardFailures.toMutableList()
51+
}
52+
53+
@Throws(IOException::class)
54+
override fun toXContent(builder: XContentBuilder, params: Params?): XContentBuilder? {
55+
builder.startObject()
56+
RestActions.buildBroadcastShardsHeader(builder, params, totalShards, successfulShards, -1, failedShards, shardFailures.toTypedArray())
57+
builder.startArray("successful_refresh_details")
58+
val successfulIndices = getSuccessfulRefreshDetails()
59+
for (index in successfulIndices.keys) {
60+
val reloadedAnalyzers = successfulIndices.get(index)!!
61+
builder.startObject().field("index", index).startArray("refreshed_analyzers")
62+
for (analyzer in reloadedAnalyzers) {
63+
builder.value(analyzer)
64+
}
65+
builder.endArray().endObject()
66+
}
67+
builder.endArray().endObject()
68+
return builder
69+
}
70+
71+
// TODO: restrict it for testing
72+
fun getSuccessfulRefreshDetails(): MutableMap<String, List<String>> {
73+
var successfulRefreshDetails: MutableMap<String, List<String>> = HashMap()
74+
var failedIndices = mutableSetOf<String>()
75+
for (failure in shardFailures) {
76+
failedIndices.add(failure.index()!!)
77+
}
78+
for (response in shardResponses) {
79+
if (!failedIndices.contains(response.index)) {
80+
successfulRefreshDetails.putIfAbsent(response.index, response.reloadedAnalyzers)
81+
}
82+
}
83+
return successfulRefreshDetails
84+
}
85+
86+
companion object {
87+
private val PARSER = ConstructingObjectParser<RefreshSearchAnalyzerResponse, Void>("_refresh_search_analyzers", true,
88+
Function { arg: Array<Any> ->
89+
val response = arg[0] as RefreshSearchAnalyzerResponse
90+
RefreshSearchAnalyzerResponse(response.totalShards, response.successfulShards, response.failedShards,
91+
response.shardFailures, response.shardResponses)
92+
})
93+
init {
94+
declareBroadcastFields(PARSER)
95+
}
96+
}
97+
98+
@Throws(IOException::class)
99+
override fun writeTo(out: StreamOutput) {
100+
super.writeTo(out)
101+
out.writeCollection(shardResponses)
102+
out.writeCollection(shardFailures)
103+
}
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer
17+
18+
import org.elasticsearch.action.support.broadcast.BroadcastShardResponse
19+
import org.elasticsearch.common.io.stream.StreamInput
20+
import org.elasticsearch.common.io.stream.StreamOutput
21+
import org.elasticsearch.index.shard.ShardId
22+
import java.io.IOException
23+
24+
class RefreshSearchAnalyzerShardResponse : BroadcastShardResponse {
25+
var reloadedAnalyzers: List<String>
26+
27+
constructor(si: StreamInput) : super(si) {
28+
reloadedAnalyzers = si.readStringArray().toList()
29+
}
30+
31+
constructor(shardId: ShardId, reloadedAnalyzers: List<String>) : super(shardId) {
32+
this.reloadedAnalyzers = reloadedAnalyzers
33+
}
34+
35+
@Throws(IOException::class)
36+
override fun writeTo(out: StreamOutput) {
37+
super.writeTo(out)
38+
out.writeStringArray(reloadedAnalyzers.toTypedArray())
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.opendistroforelasticsearch.indexmanagement.refreshanalyzer
17+
18+
import com.amazon.opendistroforelasticsearch.indexmanagement.IndexManagementPlugin.Companion.OPEN_DISTRO_BASE_URI
19+
import org.elasticsearch.client.node.NodeClient
20+
import org.elasticsearch.common.Strings
21+
import org.elasticsearch.rest.BaseRestHandler
22+
import org.elasticsearch.rest.RestHandler.Route
23+
import org.elasticsearch.rest.RestRequest
24+
import org.elasticsearch.rest.RestRequest.Method.POST
25+
import org.elasticsearch.rest.action.RestToXContentListener
26+
import java.io.IOException
27+
28+
class RestRefreshSearchAnalyzerAction : BaseRestHandler() {
29+
30+
override fun getName(): String = "refresh_search_analyzer_action"
31+
32+
override fun routes(): List<Route> {
33+
return listOf(
34+
Route(POST, REFRESH_SEARCH_ANALYZER_BASE_URI),
35+
Route(POST, "$REFRESH_SEARCH_ANALYZER_BASE_URI/{index}")
36+
)
37+
}
38+
39+
// TODO: Add indicesOptions?
40+
41+
@Throws(IOException::class)
42+
@Suppress("SpreadOperator")
43+
override fun prepareRequest(request: RestRequest, client: NodeClient): RestChannelConsumer {
44+
val indices: Array<String>? = Strings.splitStringByCommaToArray(request.param("index"))
45+
46+
if (indices.isNullOrEmpty()) {
47+
throw IllegalArgumentException("Missing indices")
48+
}
49+
50+
val refreshSearchAnalyzerRequest: RefreshSearchAnalyzerRequest = RefreshSearchAnalyzerRequest()
51+
.indices(*indices)
52+
53+
return RestChannelConsumer { channel ->
54+
client.execute(RefreshSearchAnalyzerAction.INSTANCE, refreshSearchAnalyzerRequest, RestToXContentListener(channel))
55+
}
56+
}
57+
58+
companion object {
59+
const val REFRESH_SEARCH_ANALYZER_BASE_URI = "$OPEN_DISTRO_BASE_URI/_refresh_search_analyzers"
60+
}
61+
}

0 commit comments

Comments
 (0)