Skip to content

Commit 09c73a2

Browse files
committed
Run TransportGetComponentTemplateAction on local node
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` and `?master_timeout` parameters become a no-op and are marked as deprecated. Relates #101805 Relates #107984
1 parent 87c2495 commit 09c73a2

File tree

7 files changed

+73
-110
lines changed

7 files changed

+73
-110
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@
2727
},
2828
"params":{
2929
"master_timeout":{
30+
"deprecated":true,
3031
"type":"time",
3132
"description":"Explicit operation timeout for connection to master node"
3233
},
3334
"local":{
35+
"deprecated":true,
3436
"type":"boolean",
3537
"description":"Return local information, do not retrieve the state from master node (default: false)"
3638
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@
3333
},
3434
"params":{
3535
"master_timeout":{
36+
"deprecated":true,
3637
"type":"time",
3738
"description":"Explicit operation timeout for connection to master node"
3839
},
3940
"local":{
41+
"deprecated":true,
4042
"type":"boolean",
4143
"description":"Return local information, do not retrieve the state from master node (default: false)"
4244
},

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

Lines changed: 13 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@
99

1010
package org.elasticsearch.action.admin.indices.template.get;
1111

12-
import org.elasticsearch.TransportVersions;
12+
import org.elasticsearch.action.ActionRequest;
1313
import org.elasticsearch.action.ActionRequestValidationException;
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.TransportAction;
1818
import org.elasticsearch.cluster.metadata.ComponentTemplate;
1919
import org.elasticsearch.cluster.metadata.DataStreamGlobalRetention;
20-
import org.elasticsearch.common.io.stream.StreamInput;
2120
import org.elasticsearch.common.io.stream.StreamOutput;
2221
import org.elasticsearch.core.Nullable;
22+
import org.elasticsearch.tasks.CancellableTask;
23+
import org.elasticsearch.tasks.Task;
24+
import org.elasticsearch.tasks.TaskId;
2325
import org.elasticsearch.xcontent.ParseField;
2426
import org.elasticsearch.xcontent.ToXContentObject;
2527
import org.elasticsearch.xcontent.XContentBuilder;
@@ -43,46 +45,32 @@ private GetComponentTemplateAction() {
4345
/**
4446
* Request that to retrieve one or more component templates
4547
*/
46-
public static class Request extends MasterNodeReadRequest<Request> {
48+
public static class Request extends ActionRequest {
4749

4850
@Nullable
4951
private String name;
5052
private boolean includeDefaults;
5153

52-
public Request() {
53-
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT);
54-
}
55-
5654
public Request(String name) {
57-
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT);
5855
this.name = name;
5956
this.includeDefaults = false;
6057
}
6158

62-
public Request(StreamInput in) throws IOException {
63-
super(in);
64-
name = in.readOptionalString();
65-
if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
66-
includeDefaults = in.readBoolean();
67-
} else {
68-
includeDefaults = false;
69-
}
70-
}
71-
7259
@Override
7360
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-
}
61+
TransportAction.localOnly();
7962
}
8063

8164
@Override
8265
public ActionRequestValidationException validate() {
8366
return null;
8467
}
8568

69+
@Override
70+
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
71+
return new CancellableTask(id, type, action, "", parentTaskId, headers);
72+
}
73+
8674
/**
8775
* Sets the name of the component templates.
8876
*/
@@ -123,20 +111,6 @@ public static class Response extends ActionResponse implements ToXContentObject
123111
@Nullable
124112
private final RolloverConfiguration rolloverConfiguration;
125113

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().onOrAfter(TransportVersions.V_8_14_0)
135-
&& in.getTransportVersion().before(TransportVersions.REMOVE_GLOBAL_RETENTION_FROM_TEMPLATES)) {
136-
in.readOptionalWriteable(DataStreamGlobalRetention::read);
137-
}
138-
}
139-
140114
/**
141115
* Please use {@link GetComponentTemplateAction.Response#Response(Map)}
142116
*/
@@ -186,14 +160,7 @@ public DataStreamGlobalRetention getGlobalRetention() {
186160

187161
@Override
188162
public void writeTo(StreamOutput out) throws IOException {
189-
out.writeMap(componentTemplates, StreamOutput::writeWriteable);
190-
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
191-
out.writeOptionalWriteable(rolloverConfiguration);
192-
}
193-
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_14_0)
194-
&& out.getTransportVersion().before(TransportVersions.REMOVE_GLOBAL_RETENTION_FROM_TEMPLATES)) {
195-
out.writeOptionalWriteable(null);
196-
}
163+
TransportAction.localOnly();
197164
}
198165

199166
@Override

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,25 @@
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.TransportLocalClusterStateAction;
1616
import org.elasticsearch.cluster.ClusterState;
1717
import org.elasticsearch.cluster.block.ClusterBlockException;
1818
import org.elasticsearch.cluster.block.ClusterBlockLevel;
1919
import org.elasticsearch.cluster.metadata.ComponentTemplate;
2020
import org.elasticsearch.cluster.metadata.DataStreamLifecycle;
21-
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
2221
import org.elasticsearch.cluster.service.ClusterService;
2322
import org.elasticsearch.common.regex.Regex;
2423
import org.elasticsearch.common.settings.ClusterSettings;
2524
import org.elasticsearch.common.util.concurrent.EsExecutors;
2625
import org.elasticsearch.injection.guice.Inject;
26+
import org.elasticsearch.tasks.CancellableTask;
2727
import org.elasticsearch.tasks.Task;
28-
import org.elasticsearch.threadpool.ThreadPool;
2928
import org.elasticsearch.transport.TransportService;
3029

3130
import java.util.HashMap;
3231
import java.util.Map;
3332

34-
public class TransportGetComponentTemplateAction extends TransportMasterNodeReadAction<
33+
public class TransportGetComponentTemplateAction extends TransportLocalClusterStateAction<
3534
GetComponentTemplateAction.Request,
3635
GetComponentTemplateAction.Response> {
3736

@@ -41,19 +40,13 @@ public class TransportGetComponentTemplateAction extends TransportMasterNodeRead
4140
public TransportGetComponentTemplateAction(
4241
TransportService transportService,
4342
ClusterService clusterService,
44-
ThreadPool threadPool,
45-
ActionFilters actionFilters,
46-
IndexNameExpressionResolver indexNameExpressionResolver
43+
ActionFilters actionFilters
4744
) {
4845
super(
4946
GetComponentTemplateAction.NAME,
50-
transportService,
51-
clusterService,
52-
threadPool,
5347
actionFilters,
54-
GetComponentTemplateAction.Request::new,
55-
indexNameExpressionResolver,
56-
GetComponentTemplateAction.Response::new,
48+
transportService.getTaskManager(),
49+
clusterService,
5750
EsExecutors.DIRECT_EXECUTOR_SERVICE
5851
);
5952
clusterSettings = clusterService.getClusterSettings();
@@ -65,12 +58,13 @@ protected ClusterBlockException checkBlock(GetComponentTemplateAction.Request re
6558
}
6659

6760
@Override
68-
protected void masterOperation(
61+
protected void localClusterStateOperation(
6962
Task task,
7063
GetComponentTemplateAction.Request request,
7164
ClusterState state,
7265
ActionListener<GetComponentTemplateAction.Response> listener
7366
) {
67+
final var cancellableTask = (CancellableTask) task;
7468
Map<String, ComponentTemplate> allTemplates = state.metadata().componentTemplates();
7569
Map<String, ComponentTemplate> results;
7670

@@ -93,6 +87,7 @@ protected void masterOperation(
9387

9488
}
9589
}
90+
cancellableTask.ensureNotCancelled();
9691
if (request.includeDefaults()) {
9792
listener.onResponse(
9893
new GetComponentTemplateAction.Response(

server/src/main/java/org/elasticsearch/action/support/TransportLocalClusterStateAction.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
import org.elasticsearch.cluster.ClusterState;
1717
import org.elasticsearch.cluster.block.ClusterBlockException;
1818
import org.elasticsearch.cluster.service.ClusterService;
19+
import org.elasticsearch.common.logging.DeprecationCategory;
20+
import org.elasticsearch.common.logging.DeprecationLogger;
1921
import org.elasticsearch.common.util.concurrent.EsExecutors;
22+
import org.elasticsearch.core.UpdateForV10;
2023
import org.elasticsearch.tasks.Task;
2124
import org.elasticsearch.tasks.TaskManager;
25+
import org.elasticsearch.xcontent.ToXContent;
2226

2327
import java.util.concurrent.Executor;
2428

@@ -61,4 +65,33 @@ protected final void doExecute(Task task, Request request, ActionListener<Respon
6165

6266
protected abstract void localClusterStateOperation(Task task, Request request, ClusterState state, ActionListener<Response> listener)
6367
throws Exception;
68+
69+
// Remove the BWC support for the deprecated ?master_timeout parameter.
70+
// NOTE: ensure each usage of this method has been deprecated for long enough to remove it.
71+
@UpdateForV10(owner = UpdateForV10.Owner.DISTRIBUTED_COORDINATION)
72+
public static void consumeDeprecatedMasterTimeoutParameter(ToXContent.Params params) {
73+
if (params.paramAsBoolean("master_timeout", false)) {
74+
DeprecationLogger.getLogger(TransportLocalClusterStateAction.class)
75+
.critical(
76+
DeprecationCategory.API,
77+
"TransportLocalClusterStateAction-master-timeout-parameter",
78+
"the [?master_timeout] query parameter to this API has no effect, is now deprecated, " +
79+
"and will be removed in a future version"
80+
);
81+
}
82+
}
83+
84+
// Remove the BWC support for the deprecated ?local parameter.
85+
// NOTE: ensure each usage of this method has been deprecated for long enough to remove it.
86+
@UpdateForV10(owner = UpdateForV10.Owner.DISTRIBUTED_COORDINATION)
87+
public static void consumeDeprecatedLocalParameter(ToXContent.Params params) {
88+
if (params.paramAsBoolean("local", false)) {
89+
DeprecationLogger.getLogger(TransportLocalClusterStateAction.class)
90+
.critical(
91+
DeprecationCategory.API,
92+
"TransportLocalClusterStateAction-local-parameter",
93+
"the [?local] query parameter to this API has no effect, is now deprecated, and will be removed in a future version"
94+
);
95+
}
96+
}
6497
}

server/src/main/java/org/elasticsearch/rest/action/admin/indices/RestGetComponentTemplateAction.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010
package org.elasticsearch.rest.action.admin.indices;
1111

1212
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
13+
import org.elasticsearch.action.support.TransportLocalClusterStateAction;
1314
import org.elasticsearch.client.internal.node.NodeClient;
1415
import org.elasticsearch.common.settings.Settings;
1516
import org.elasticsearch.rest.BaseRestHandler;
1617
import org.elasticsearch.rest.RestRequest;
1718
import org.elasticsearch.rest.Scope;
1819
import org.elasticsearch.rest.ServerlessScope;
20+
import org.elasticsearch.rest.action.RestCancellableNodeClient;
1921
import org.elasticsearch.rest.action.RestToXContentListener;
2022

2123
import java.io.IOException;
@@ -26,7 +28,6 @@
2628
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
2729
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
2830
import static org.elasticsearch.rest.RestStatus.OK;
29-
import static org.elasticsearch.rest.RestUtils.getMasterNodeTimeout;
3031

3132
@ServerlessScope(Scope.PUBLIC)
3233
public class RestGetComponentTemplateAction extends BaseRestHandler {
@@ -50,15 +51,19 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
5051

5152
final GetComponentTemplateAction.Request getRequest = new GetComponentTemplateAction.Request(request.param("name"));
5253
getRequest.includeDefaults(request.paramAsBoolean("include_defaults", false));
53-
getRequest.local(request.paramAsBoolean("local", getRequest.local()));
54-
getRequest.masterNodeTimeout(getMasterNodeTimeout(request));
54+
TransportLocalClusterStateAction.consumeDeprecatedLocalParameter(request);
55+
TransportLocalClusterStateAction.consumeDeprecatedMasterTimeoutParameter(request);
5556

5657
final boolean implicitAll = getRequest.name() == null;
5758

58-
return channel -> client.execute(GetComponentTemplateAction.INSTANCE, getRequest, new RestToXContentListener<>(channel, r -> {
59-
final boolean templateExists = r.getComponentTemplates().isEmpty() == false;
60-
return (templateExists || implicitAll) ? OK : NOT_FOUND;
61-
}));
59+
return channel -> new RestCancellableNodeClient(client, request.getHttpChannel()).execute(
60+
GetComponentTemplateAction.INSTANCE,
61+
getRequest,
62+
new RestToXContentListener<>(channel, r -> {
63+
final boolean templateExists = r.getComponentTemplates().isEmpty() == false;
64+
return (templateExists || implicitAll) ? OK : NOT_FOUND;
65+
})
66+
);
6267
}
6368

6469
@Override

server/src/test/java/org/elasticsearch/action/admin/indices/template/get/GetComponentTemplateResponseTests.java

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,16 @@
1212
import org.elasticsearch.action.admin.indices.rollover.RolloverConfigurationTests;
1313
import org.elasticsearch.cluster.metadata.AliasMetadata;
1414
import org.elasticsearch.cluster.metadata.ComponentTemplate;
15-
import org.elasticsearch.cluster.metadata.ComponentTemplateTests;
1615
import org.elasticsearch.cluster.metadata.DataStreamLifecycle;
1716
import org.elasticsearch.cluster.metadata.Template;
1817
import org.elasticsearch.common.Strings;
1918
import org.elasticsearch.common.compress.CompressedXContent;
20-
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
21-
import org.elasticsearch.common.io.stream.Writeable;
2219
import org.elasticsearch.common.settings.Settings;
23-
import org.elasticsearch.indices.IndicesModule;
24-
import org.elasticsearch.test.AbstractWireSerializingTestCase;
20+
import org.elasticsearch.test.ESTestCase;
2521
import org.elasticsearch.xcontent.XContentBuilder;
2622
import org.elasticsearch.xcontent.XContentType;
2723

2824
import java.io.IOException;
29-
import java.util.HashMap;
3025
import java.util.Map;
3126

3227
import static org.elasticsearch.cluster.metadata.ComponentTemplateTests.randomAliases;
@@ -35,30 +30,7 @@
3530
import static org.elasticsearch.xcontent.ToXContent.EMPTY_PARAMS;
3631
import static org.hamcrest.Matchers.containsString;
3732

38-
public class GetComponentTemplateResponseTests extends AbstractWireSerializingTestCase<GetComponentTemplateAction.Response> {
39-
@Override
40-
protected Writeable.Reader<GetComponentTemplateAction.Response> instanceReader() {
41-
return GetComponentTemplateAction.Response::new;
42-
}
43-
44-
@Override
45-
protected GetComponentTemplateAction.Response createTestInstance() {
46-
return new GetComponentTemplateAction.Response(
47-
randomBoolean() ? Map.of() : randomTemplates(),
48-
RolloverConfigurationTests.randomRolloverConditions()
49-
);
50-
}
51-
52-
@Override
53-
protected GetComponentTemplateAction.Response mutateInstance(GetComponentTemplateAction.Response instance) {
54-
var templates = instance.getComponentTemplates();
55-
var rolloverConditions = instance.getRolloverConfiguration();
56-
switch (randomInt(1)) {
57-
case 0 -> templates = templates == null ? randomTemplates() : null;
58-
case 1 -> rolloverConditions = randomValueOtherThan(rolloverConditions, RolloverConfigurationTests::randomRolloverConditions);
59-
}
60-
return new GetComponentTemplateAction.Response(templates, rolloverConditions);
61-
}
33+
public class GetComponentTemplateResponseTests extends ESTestCase {
6234

6335
public void testXContentSerializationWithRolloverAndEffectiveRetention() throws IOException {
6436
Settings settings = null;
@@ -96,17 +68,4 @@ public void testXContentSerializationWithRolloverAndEffectiveRetention() throws
9668
}
9769
}
9870
}
99-
100-
@Override
101-
protected NamedWriteableRegistry getNamedWriteableRegistry() {
102-
return new NamedWriteableRegistry(IndicesModule.getNamedWriteables());
103-
}
104-
105-
private static Map<String, ComponentTemplate> randomTemplates() {
106-
Map<String, ComponentTemplate> templates = new HashMap<>();
107-
for (int i = 0; i < randomIntBetween(1, 4); i++) {
108-
templates.put(randomAlphaOfLength(4), ComponentTemplateTests.randomInstance());
109-
}
110-
return templates;
111-
}
11271
}

0 commit comments

Comments
 (0)