Skip to content

Commit 481d91c

Browse files
authored
Run TransportGetMappingsAction on local node (#122921)
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. Relates #101805
1 parent 6a748b5 commit 481d91c

File tree

12 files changed

+133
-80
lines changed

12 files changed

+133
-80
lines changed

docs/changelog/122921.yaml

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

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsAction;
1616
import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
1717
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
18+
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsAction;
1819
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
1920
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
2021
import org.elasticsearch.action.admin.indices.template.get.GetComposableIndexTemplateAction;
@@ -108,6 +109,11 @@ public void testGetPipelineCancellation() {
108109
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/_ingest/pipeline"), GetPipelineAction.NAME);
109110
}
110111

112+
public void testGetMappingsCancellation() {
113+
createIndex("test");
114+
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/test/_mappings"), GetMappingsAction.NAME);
115+
}
116+
111117
private void runRestActionCancellationTest(Request request, String actionName) {
112118
final var node = usually() ? internalCluster().getRandomNodeName() : internalCluster().startCoordinatingOnlyNode(Settings.EMPTY);
113119

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import org.apache.http.client.methods.HttpGet;
1313
import org.elasticsearch.action.admin.indices.get.GetIndexAction;
14-
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsAction;
1514
import org.elasticsearch.action.support.PlainActionFuture;
1615
import org.elasticsearch.action.support.master.AcknowledgedResponse;
1716
import org.elasticsearch.client.Cancellable;
@@ -41,10 +40,6 @@
4140
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 0, numClientNodes = 0)
4241
public class RestClusterInfoActionCancellationIT extends HttpSmokeTestCase {
4342

44-
public void testGetMappingsCancellation() throws Exception {
45-
runTest(GetMappingsAction.NAME, "/test/_mappings");
46-
}
47-
4843
public void testGetIndicesCancellation() throws Exception {
4944
runTest(GetIndexAction.NAME, "/test");
5045
}

rest-api-spec/src/main/resources/rest-api-spec/api/indices.get_mapping.json

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,12 @@
5454
},
5555
"master_timeout":{
5656
"type":"time",
57-
"description":"Specify timeout for connection to master"
57+
"description":"Timeout for waiting for new cluster state in case it is blocked"
5858
},
5959
"local":{
6060
"type":"boolean",
6161
"description":"Return local information, do not retrieve the state from master node (default: false)",
62-
"deprecated":{
63-
"version":"7.8.0",
64-
"description":"This parameter is a no-op and field mappings are always retrieved locally."
65-
}
62+
"deprecated":true
6663
}
6764
}
6865
}

server/src/internalClusterTest/java/org/elasticsearch/action/IndicesRequestIT.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
2525
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsAction;
2626
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
27-
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsAction;
28-
import org.elasticsearch.action.admin.indices.mapping.get.GetMappingsRequest;
2927
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
3028
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
3129
import org.elasticsearch.action.admin.indices.open.OpenIndexAction;
@@ -516,16 +514,6 @@ public void testDeleteIndex() {
516514
assertSameIndices(deleteIndexRequest, TransportDeleteIndexAction.TYPE.name());
517515
}
518516

519-
public void testGetMappings() {
520-
interceptTransportActions(GetMappingsAction.NAME);
521-
522-
GetMappingsRequest getMappingsRequest = new GetMappingsRequest(TEST_REQUEST_TIMEOUT).indices(randomIndicesOrAliases());
523-
internalCluster().coordOnlyNodeClient().admin().indices().getMappings(getMappingsRequest).actionGet();
524-
525-
clearInterceptedActions();
526-
assertSameIndices(getMappingsRequest, GetMappingsAction.NAME);
527-
}
528-
529517
public void testPutMapping() {
530518
interceptTransportActions(TransportPutMappingAction.TYPE.name());
531519

server/src/internalClusterTest/java/org/elasticsearch/cluster/SimpleClusterStateIT.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,6 @@ public void testLargeClusterStatePublishing() throws Exception {
266266
MappingMetadata mappingMetadata = client.admin()
267267
.indices()
268268
.prepareGetMappings(TEST_REQUEST_TIMEOUT, "test")
269-
.setLocal(true)
270269
.get()
271270
.getMappings()
272271
.get("test");

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsRequest.java

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,44 @@
99

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

12+
import org.elasticsearch.TransportVersions;
1213
import org.elasticsearch.action.ActionRequestValidationException;
14+
import org.elasticsearch.action.IndicesRequest;
1315
import org.elasticsearch.action.support.IndicesOptions;
14-
import org.elasticsearch.action.support.master.info.ClusterInfoRequest;
16+
import org.elasticsearch.action.support.local.LocalClusterStateRequest;
17+
import org.elasticsearch.common.Strings;
1518
import org.elasticsearch.common.io.stream.StreamInput;
1619
import org.elasticsearch.core.TimeValue;
20+
import org.elasticsearch.core.UpdateForV10;
1721
import org.elasticsearch.tasks.CancellableTask;
1822
import org.elasticsearch.tasks.Task;
1923
import org.elasticsearch.tasks.TaskId;
2024

2125
import java.io.IOException;
2226
import java.util.Map;
2327

24-
public class GetMappingsRequest extends ClusterInfoRequest<GetMappingsRequest> {
28+
public class GetMappingsRequest extends LocalClusterStateRequest implements IndicesRequest.Replaceable {
29+
30+
private String[] indices = Strings.EMPTY_ARRAY;
31+
private IndicesOptions indicesOptions;
2532

2633
public GetMappingsRequest(TimeValue masterTimeout) {
27-
super(masterTimeout, IndicesOptions.strictExpandOpen());
34+
super(masterTimeout);
35+
indicesOptions = IndicesOptions.strictExpandOpen();
2836
}
2937

38+
/**
39+
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC we must remain able to read these requests until
40+
* we no longer need to support calling this action remotely.
41+
*/
42+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
3043
public GetMappingsRequest(StreamInput in) throws IOException {
3144
super(in);
45+
indices = in.readStringArray();
46+
if (in.getTransportVersion().before(TransportVersions.V_8_0_0)) {
47+
in.readStringArray();
48+
}
49+
indicesOptions = IndicesOptions.readIndicesOptions(in);
3250
}
3351

3452
@Override
@@ -40,4 +58,30 @@ public ActionRequestValidationException validate() {
4058
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
4159
return new CancellableTask(id, type, action, "", parentTaskId, headers);
4260
}
61+
62+
@Override
63+
public GetMappingsRequest indices(String... indices) {
64+
this.indices = indices;
65+
return this;
66+
}
67+
68+
public GetMappingsRequest indicesOptions(IndicesOptions indicesOptions) {
69+
this.indicesOptions = indicesOptions;
70+
return this;
71+
}
72+
73+
@Override
74+
public String[] indices() {
75+
return indices;
76+
}
77+
78+
@Override
79+
public IndicesOptions indicesOptions() {
80+
return indicesOptions;
81+
}
82+
83+
@Override
84+
public boolean includeDataStreams() {
85+
return true;
86+
}
4387
}

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsRequestBuilder.java

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,30 @@
99

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

12-
import org.elasticsearch.action.support.master.info.ClusterInfoRequestBuilder;
12+
import org.elasticsearch.action.ActionRequestBuilder;
13+
import org.elasticsearch.action.support.IndicesOptions;
1314
import org.elasticsearch.client.internal.ElasticsearchClient;
15+
import org.elasticsearch.common.util.ArrayUtils;
1416
import org.elasticsearch.core.TimeValue;
1517

16-
public class GetMappingsRequestBuilder extends ClusterInfoRequestBuilder<
17-
GetMappingsRequest,
18-
GetMappingsResponse,
19-
GetMappingsRequestBuilder> {
18+
public class GetMappingsRequestBuilder extends ActionRequestBuilder<GetMappingsRequest, GetMappingsResponse> {
2019

2120
public GetMappingsRequestBuilder(ElasticsearchClient client, TimeValue masterTimeout, String... indices) {
2221
super(client, GetMappingsAction.INSTANCE, new GetMappingsRequest(masterTimeout).indices(indices));
2322
}
23+
24+
public GetMappingsRequestBuilder setIndices(String... indices) {
25+
request.indices(indices);
26+
return this;
27+
}
28+
29+
public GetMappingsRequestBuilder addIndices(String... indices) {
30+
request.indices(ArrayUtils.concat(request.indices(), indices));
31+
return this;
32+
}
33+
34+
public GetMappingsRequestBuilder setIndicesOptions(IndicesOptions indicesOptions) {
35+
request.indicesOptions(indicesOptions);
36+
return this;
37+
}
2438
}

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetMappingsResponse.java

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,13 @@
99

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

12-
import org.elasticsearch.TransportVersions;
1312
import org.elasticsearch.action.ActionResponse;
1413
import org.elasticsearch.cluster.metadata.MappingMetadata;
1514
import org.elasticsearch.common.Strings;
1615
import org.elasticsearch.common.collect.Iterators;
17-
import org.elasticsearch.common.io.stream.StreamInput;
1816
import org.elasticsearch.common.io.stream.StreamOutput;
1917
import org.elasticsearch.common.xcontent.ChunkedToXContentObject;
20-
import org.elasticsearch.index.mapper.MapperService;
18+
import org.elasticsearch.core.UpdateForV10;
2119
import org.elasticsearch.xcontent.ParseField;
2220
import org.elasticsearch.xcontent.ToXContent;
2321

@@ -35,21 +33,6 @@ public GetMappingsResponse(Map<String, MappingMetadata> mappings) {
3533
this.mappings = mappings;
3634
}
3735

38-
GetMappingsResponse(StreamInput in) throws IOException {
39-
super(in);
40-
mappings = in.readImmutableMap(in.getTransportVersion().before(TransportVersions.V_8_0_0) ? i -> {
41-
int mappingCount = i.readVInt();
42-
assert mappingCount == 1 || mappingCount == 0 : "Expected 0 or 1 mappings but got " + mappingCount;
43-
if (mappingCount == 1) {
44-
String type = i.readString();
45-
assert MapperService.SINGLE_MAPPING_NAME.equals(type) : "Expected type [_doc] but got [" + type + "]";
46-
return new MappingMetadata(i);
47-
} else {
48-
return MappingMetadata.EMPTY_MAPPINGS;
49-
}
50-
} : i -> i.readBoolean() ? new MappingMetadata(i) : MappingMetadata.EMPTY_MAPPINGS);
51-
}
52-
5336
public Map<String, MappingMetadata> mappings() {
5437
return mappings;
5538
}
@@ -58,6 +41,11 @@ public Map<String, MappingMetadata> getMappings() {
5841
return mappings();
5942
}
6043

44+
/**
45+
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC we must remain able to write these responses until
46+
* we no longer need to support calling this action remotely.
47+
*/
48+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
6149
@Override
6250
public void writeTo(StreamOutput out) throws IOException {
6351
MappingMetadata.writeMappingMetadata(out, mappings);

server/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/TransportGetMappingsAction.java

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,16 @@
1313
import org.apache.logging.log4j.Logger;
1414
import org.elasticsearch.action.ActionListener;
1515
import org.elasticsearch.action.support.ActionFilters;
16-
import org.elasticsearch.action.support.master.info.TransportClusterInfoAction;
17-
import org.elasticsearch.cluster.ClusterState;
16+
import org.elasticsearch.action.support.ChannelActionListener;
17+
import org.elasticsearch.action.support.local.TransportLocalProjectMetadataAction;
18+
import org.elasticsearch.cluster.ProjectState;
19+
import org.elasticsearch.cluster.block.ClusterBlockException;
20+
import org.elasticsearch.cluster.block.ClusterBlockLevel;
1821
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
1922
import org.elasticsearch.cluster.metadata.MappingMetadata;
2023
import org.elasticsearch.cluster.project.ProjectResolver;
2124
import org.elasticsearch.cluster.service.ClusterService;
25+
import org.elasticsearch.core.UpdateForV10;
2226
import org.elasticsearch.indices.IndicesService;
2327
import org.elasticsearch.injection.guice.Inject;
2428
import org.elasticsearch.tasks.CancellableTask;
@@ -28,12 +32,19 @@
2832

2933
import java.util.Map;
3034

31-
public class TransportGetMappingsAction extends TransportClusterInfoAction<GetMappingsRequest, GetMappingsResponse> {
35+
public class TransportGetMappingsAction extends TransportLocalProjectMetadataAction<GetMappingsRequest, GetMappingsResponse> {
3236

3337
private static final Logger logger = LogManager.getLogger(TransportGetMappingsAction.class);
3438

3539
private final IndicesService indicesService;
40+
private final IndexNameExpressionResolver indexNameExpressionResolver;
3641

42+
/**
43+
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until
44+
* we no longer need to support calling this action remotely.
45+
*/
46+
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
47+
@SuppressWarnings("this-escape")
3748
@Inject
3849
public TransportGetMappingsAction(
3950
TransportService transportService,
@@ -46,28 +57,46 @@ public TransportGetMappingsAction(
4657
) {
4758
super(
4859
GetMappingsAction.NAME,
49-
transportService,
50-
clusterService,
51-
threadPool,
5260
actionFilters,
53-
GetMappingsRequest::new,
54-
indexNameExpressionResolver,
55-
GetMappingsResponse::new,
61+
transportService.getTaskManager(),
62+
clusterService,
63+
threadPool.executor(ThreadPool.Names.MANAGEMENT),
5664
projectResolver
5765
);
5866
this.indicesService = indicesService;
67+
this.indexNameExpressionResolver = indexNameExpressionResolver;
68+
69+
transportService.registerRequestHandler(
70+
actionName,
71+
executor,
72+
false,
73+
true,
74+
GetMappingsRequest::new,
75+
(request, channel, task) -> executeDirect(task, request, new ChannelActionListener<>(channel))
76+
);
77+
}
78+
79+
@Override
80+
protected ClusterBlockException checkBlock(GetMappingsRequest request, ProjectState state) {
81+
return state.blocks()
82+
.indicesBlockedException(
83+
state.projectId(),
84+
ClusterBlockLevel.METADATA_READ,
85+
indexNameExpressionResolver.concreteIndexNames(state.metadata(), request)
86+
);
5987
}
6088

6189
@Override
62-
protected void doMasterOperation(
90+
protected void localClusterStateOperation(
6391
Task task,
6492
final GetMappingsRequest request,
65-
String[] concreteIndices,
66-
final ClusterState state,
93+
final ProjectState state,
6794
final ActionListener<GetMappingsResponse> listener
6895
) {
69-
logger.trace("serving getMapping request based on version {}", state.version());
70-
final Map<String, MappingMetadata> mappings = projectResolver.getProjectMetadata(state)
96+
((CancellableTask) task).ensureNotCancelled();
97+
logger.trace("serving getMapping request based on version {}", state.cluster().version());
98+
String[] concreteIndices = indexNameExpressionResolver.concreteIndexNames(state.metadata(), request);
99+
final Map<String, MappingMetadata> mappings = state.metadata()
71100
.findMappings(concreteIndices, indicesService.getFieldFilter(), () -> checkCancellation(task));
72101
listener.onResponse(new GetMappingsResponse(mappings));
73102
}

0 commit comments

Comments
 (0)