Skip to content

Commit 9641c76

Browse files
authored
Run TransportGetComponentTemplateAction on local node (#116868)
This action solely needs the cluster state, it can run on any node. Additionally, it needs to be cancellable to avoid doing unnecessary work after a client failure or timeout. The `?local` parameter becomes a no-op and is marked as deprecated. Relates #101805 Relates #107984
1 parent c16bcb6 commit 9641c76

File tree

15 files changed

+170
-99
lines changed

15 files changed

+170
-99
lines changed

docs/changelog/116868.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 116868
2+
summary: Run `TransportGetComponentTemplateAction` on local node
3+
area: Indices APIs
4+
type: enhancement
5+
issues: []

docs/reference/indices/get-component-template.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Wildcard (`*`) expressions are supported.
6767

6868
include::{docdir}/rest-api/common-parms.asciidoc[tag=flat-settings]
6969

70-
include::{docdir}/rest-api/common-parms.asciidoc[tag=local]
70+
include::{docdir}/rest-api/common-parms.asciidoc[tag=local-deprecated-9.0.0]
7171

7272
include::{docdir}/rest-api/common-parms.asciidoc[tag=master-timeout]
7373

docs/reference/rest-api/common-parms.asciidoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,16 @@ node only. Defaults to `false`, which means information is retrieved from
668668
the master node.
669669
end::local[]
670670

671+
tag::local-deprecated-9.0.0[]
672+
`local`::
673+
(Optional, Boolean) If `true`, the request retrieves information from the local
674+
node only. Defaults to `false`, which means information is retrieved from
675+
the master node.
676+
+
677+
deprecated::[9.0.0, "The `?local` query parameter to this API has no effect, is now deprecated, and will be removed in a future version."]
678+
679+
end::local-deprecated-9.0.0[]
680+
671681
tag::mappings[]
672682
`mappings`::
673683
+

qa/smoke-test-http/src/javaRestTest/java/org/elasticsearch/http/RestActionCancellationIT.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
1616
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
1717
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
18+
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
1819
import org.elasticsearch.action.support.CancellableActionTestPlugin;
1920
import org.elasticsearch.action.support.PlainActionFuture;
2021
import org.elasticsearch.action.support.RefCountingListener;
@@ -66,6 +67,10 @@ public void testCatAliasesCancellation() {
6667
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/_cat/aliases"), GetAliasesAction.NAME);
6768
}
6869

70+
public void testGetComponentTemplateCancellation() {
71+
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/_component_template"), GetComponentTemplateAction.NAME);
72+
}
73+
6974
private void runRestActionCancellationTest(Request request, String actionName) {
7075
final var node = usually() ? internalCluster().getRandomNodeName() : internalCluster().startCoordinatingOnlyNode(Settings.EMPTY);
7176

rest-api-spec/src/main/resources/rest-api-spec/api/cluster.exists_component_template.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
"params":{
2929
"master_timeout":{
3030
"type":"time",
31-
"description":"Explicit operation timeout for connection to master node"
31+
"description":"Timeout for waiting for new cluster state in case it is blocked"
3232
},
3333
"local":{
34+
"deprecated":true,
3435
"type":"boolean",
3536
"description":"Return local information, do not retrieve the state from master node (default: false)"
3637
}

rest-api-spec/src/main/resources/rest-api-spec/api/cluster.get_component_template.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434
"params":{
3535
"master_timeout":{
3636
"type":"time",
37-
"description":"Explicit operation timeout for connection to master node"
37+
"description":"Timeout for waiting for new cluster state in case it is blocked"
3838
},
3939
"local":{
40+
"deprecated":true,
4041
"type":"boolean",
4142
"description":"Return local information, do not retrieve the state from master node (default: false)"
4243
},

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cluster.component_template/10_basic.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,33 @@
171171
- match: {component_templates.0.component_template.template.lifecycle.enabled: true}
172172
- match: {component_templates.0.component_template.template.lifecycle.data_retention: "10d"}
173173
- is_true: component_templates.0.component_template.template.lifecycle.rollover
174+
175+
---
176+
"Deprecated local parameter":
177+
- requires:
178+
capabilities:
179+
- method: GET
180+
path: /_component_template
181+
capabilities: ["local_param_deprecated"]
182+
test_runner_features: ["capabilities", "warnings"]
183+
reason: Deprecation was implemented with capability
184+
185+
- do:
186+
cluster.get_component_template:
187+
local: true
188+
warnings:
189+
- "the [?local] query parameter to this API has no effect, is now deprecated, and will be removed in a future version"
190+
191+
---
192+
"Deprecated local parameter works in v8 compat mode":
193+
- requires:
194+
test_runner_features: ["headers"]
195+
196+
- do:
197+
headers:
198+
Content-Type: "application/vnd.elasticsearch+json;compatible-with=8"
199+
Accept: "application/vnd.elasticsearch+json;compatible-with=8"
200+
cluster.get_component_template:
201+
local: true
202+
203+
- exists: component_templates

server/src/internalClusterTest/java/org/elasticsearch/reservedstate/service/ComponentTemplatesFileSettingsIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ private void assertComponentAndIndexTemplateDelete(CountDownLatch savedClusterSt
463463

464464
final var componentResponse = client().execute(
465465
GetComponentTemplateAction.INSTANCE,
466-
new GetComponentTemplateAction.Request("other*")
466+
new GetComponentTemplateAction.Request(TEST_REQUEST_TIMEOUT, "other*")
467467
).get();
468468

469469
assertTrue(componentResponse.getComponentTemplates().isEmpty());

server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetComponentTemplateAction.java

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414
import org.elasticsearch.action.ActionResponse;
1515
import org.elasticsearch.action.ActionType;
1616
import org.elasticsearch.action.admin.indices.rollover.RolloverConfiguration;
17-
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
17+
import org.elasticsearch.action.support.local.LocalClusterStateRequest;
1818
import org.elasticsearch.cluster.metadata.ComponentTemplate;
1919
import org.elasticsearch.cluster.metadata.DataStreamGlobalRetention;
2020
import org.elasticsearch.common.io.stream.StreamInput;
2121
import org.elasticsearch.common.io.stream.StreamOutput;
2222
import org.elasticsearch.core.Nullable;
23+
import org.elasticsearch.core.TimeValue;
24+
import org.elasticsearch.core.UpdateForV10;
25+
import org.elasticsearch.tasks.CancellableTask;
26+
import org.elasticsearch.tasks.Task;
27+
import org.elasticsearch.tasks.TaskId;
2328
import org.elasticsearch.xcontent.ParseField;
2429
import org.elasticsearch.xcontent.ToXContentObject;
2530
import org.elasticsearch.xcontent.XContentBuilder;
@@ -43,22 +48,23 @@ private GetComponentTemplateAction() {
4348
/**
4449
* Request that to retrieve one or more component templates
4550
*/
46-
public static class Request extends MasterNodeReadRequest<Request> {
51+
public static class Request extends LocalClusterStateRequest {
4752

4853
@Nullable
4954
private String name;
5055
private boolean includeDefaults;
5156

52-
public Request() {
53-
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT);
54-
}
55-
56-
public Request(String name) {
57-
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT);
57+
public Request(TimeValue masterTimeout, String name) {
58+
super(masterTimeout);
5859
this.name = name;
5960
this.includeDefaults = false;
6061
}
6162

63+
/**
64+
* NB prior to 9.0 get-component was a TransportMasterNodeReadAction so for BwC we must remain able to read these requests until
65+
* we no longer need to support calling this action remotely.
66+
*/
67+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
6268
public Request(StreamInput in) throws IOException {
6369
super(in);
6470
name = in.readOptionalString();
@@ -70,17 +76,13 @@ public Request(StreamInput in) throws IOException {
7076
}
7177

7278
@Override
73-
public void writeTo(StreamOutput out) throws IOException {
74-
super.writeTo(out);
75-
out.writeOptionalString(name);
76-
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
77-
out.writeBoolean(includeDefaults);
78-
}
79+
public ActionRequestValidationException validate() {
80+
return null;
7981
}
8082

8183
@Override
82-
public ActionRequestValidationException validate() {
83-
return null;
84+
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
85+
return new CancellableTask(id, type, action, "", parentTaskId, headers);
8486
}
8587

8688
/**
@@ -123,19 +125,6 @@ public static class Response extends ActionResponse implements ToXContentObject
123125
@Nullable
124126
private final RolloverConfiguration rolloverConfiguration;
125127

126-
public Response(StreamInput in) throws IOException {
127-
super(in);
128-
componentTemplates = in.readMap(ComponentTemplate::new);
129-
if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
130-
rolloverConfiguration = in.readOptionalWriteable(RolloverConfiguration::new);
131-
} else {
132-
rolloverConfiguration = null;
133-
}
134-
if (in.getTransportVersion().between(TransportVersions.V_8_14_0, TransportVersions.V_8_16_0)) {
135-
in.readOptionalWriteable(DataStreamGlobalRetention::read);
136-
}
137-
}
138-
139128
/**
140129
* Please use {@link GetComponentTemplateAction.Response#Response(Map)}
141130
*/
@@ -183,6 +172,11 @@ public DataStreamGlobalRetention getGlobalRetention() {
183172
return null;
184173
}
185174

175+
/**
176+
* NB prior to 9.0 get-component was a TransportMasterNodeReadAction so for BwC we must remain able to write these responses until
177+
* we no longer need to support calling this action remotely.
178+
*/
179+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
186180
@Override
187181
public void writeTo(StreamOutput out) throws IOException {
188182
out.writeMap(componentTemplates, StreamOutput::writeWriteable);

server/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetComponentTemplateAction.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,61 @@
1212
import org.elasticsearch.ResourceNotFoundException;
1313
import org.elasticsearch.action.ActionListener;
1414
import org.elasticsearch.action.support.ActionFilters;
15-
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
15+
import org.elasticsearch.action.support.ChannelActionListener;
16+
import org.elasticsearch.action.support.local.TransportLocalClusterStateAction;
1617
import org.elasticsearch.cluster.ClusterState;
1718
import org.elasticsearch.cluster.block.ClusterBlockException;
1819
import org.elasticsearch.cluster.block.ClusterBlockLevel;
1920
import org.elasticsearch.cluster.metadata.ComponentTemplate;
2021
import org.elasticsearch.cluster.metadata.DataStreamLifecycle;
21-
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
2222
import org.elasticsearch.cluster.service.ClusterService;
2323
import org.elasticsearch.common.regex.Regex;
2424
import org.elasticsearch.common.settings.ClusterSettings;
2525
import org.elasticsearch.common.util.concurrent.EsExecutors;
26+
import org.elasticsearch.core.UpdateForV10;
2627
import org.elasticsearch.injection.guice.Inject;
28+
import org.elasticsearch.tasks.CancellableTask;
2729
import org.elasticsearch.tasks.Task;
28-
import org.elasticsearch.threadpool.ThreadPool;
2930
import org.elasticsearch.transport.TransportService;
3031

3132
import java.util.HashMap;
3233
import java.util.Map;
3334

34-
public class TransportGetComponentTemplateAction extends TransportMasterNodeReadAction<
35+
public class TransportGetComponentTemplateAction extends TransportLocalClusterStateAction<
3536
GetComponentTemplateAction.Request,
3637
GetComponentTemplateAction.Response> {
3738

3839
private final ClusterSettings clusterSettings;
3940

41+
/**
42+
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until
43+
* we no longer need to support calling this action remotely.
44+
*/
45+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
46+
@SuppressWarnings("this-escape")
4047
@Inject
4148
public TransportGetComponentTemplateAction(
4249
TransportService transportService,
4350
ClusterService clusterService,
44-
ThreadPool threadPool,
45-
ActionFilters actionFilters,
46-
IndexNameExpressionResolver indexNameExpressionResolver
51+
ActionFilters actionFilters
4752
) {
4853
super(
4954
GetComponentTemplateAction.NAME,
50-
transportService,
51-
clusterService,
52-
threadPool,
5355
actionFilters,
54-
GetComponentTemplateAction.Request::new,
55-
indexNameExpressionResolver,
56-
GetComponentTemplateAction.Response::new,
56+
transportService.getTaskManager(),
57+
clusterService,
5758
EsExecutors.DIRECT_EXECUTOR_SERVICE
5859
);
5960
clusterSettings = clusterService.getClusterSettings();
61+
62+
transportService.registerRequestHandler(
63+
actionName,
64+
executor,
65+
false,
66+
true,
67+
GetComponentTemplateAction.Request::new,
68+
(request, channel, task) -> executeDirect(task, request, new ChannelActionListener<>(channel))
69+
);
6070
}
6171

6272
@Override
@@ -65,12 +75,13 @@ protected ClusterBlockException checkBlock(GetComponentTemplateAction.Request re
6575
}
6676

6777
@Override
68-
protected void masterOperation(
78+
protected void localClusterStateOperation(
6979
Task task,
7080
GetComponentTemplateAction.Request request,
7181
ClusterState state,
7282
ActionListener<GetComponentTemplateAction.Response> listener
7383
) {
84+
final var cancellableTask = (CancellableTask) task;
7485
Map<String, ComponentTemplate> allTemplates = state.metadata().componentTemplates();
7586
Map<String, ComponentTemplate> results;
7687

@@ -93,6 +104,7 @@ protected void masterOperation(
93104

94105
}
95106
}
107+
cancellableTask.ensureNotCancelled();
96108
if (request.includeDefaults()) {
97109
listener.onResponse(
98110
new GetComponentTemplateAction.Response(

0 commit comments

Comments
 (0)