Skip to content

Commit e01c115

Browse files
Lock MRT to true for eql and msearch
1 parent 687e383 commit e01c115

File tree

5 files changed

+98
-31
lines changed

5 files changed

+98
-31
lines changed

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestMultiSearchTemplateAction.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.elasticsearch.rest.action.RestToXContentListener;
1919
import org.elasticsearch.rest.action.search.RestMultiSearchAction;
2020
import org.elasticsearch.rest.action.search.RestSearchAction;
21+
import org.elasticsearch.search.crossproject.CrossProjectModeDecider;
2122
import org.elasticsearch.xcontent.XContentType;
2223

2324
import java.io.IOException;
@@ -35,11 +36,11 @@ public class RestMultiSearchTemplateAction extends BaseRestHandler {
3536
private static final Set<String> RESPONSE_PARAMS = Set.of(RestSearchAction.TYPED_KEYS_PARAM, RestSearchAction.TOTAL_HITS_AS_INT_PARAM);
3637

3738
private final boolean allowExplicitIndex;
38-
private final Settings settings;
39+
private final CrossProjectModeDecider crossProjectModeDecider;
3940

4041
public RestMultiSearchTemplateAction(Settings settings) {
4142
this.allowExplicitIndex = MULTI_ALLOW_EXPLICIT_INDEX.get(settings);
42-
this.settings = settings;
43+
this.crossProjectModeDecider = new CrossProjectModeDecider(settings);
4344
}
4445

4546
@Override
@@ -67,7 +68,8 @@ public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client
6768
* Parses a {@link RestRequest} body and returns a {@link MultiSearchTemplateRequest}
6869
*/
6970
public MultiSearchTemplateRequest parseRequest(RestRequest restRequest, boolean allowExplicitIndex) throws IOException {
70-
if (settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false)) {
71+
boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
72+
if (crossProjectEnabled) {
7173
// accept but drop project_routing param until fully supported
7274
restRequest.param("project_routing");
7375
}
@@ -90,7 +92,8 @@ public MultiSearchTemplateRequest parseRequest(RestRequest restRequest, boolean
9092
throw new IllegalArgumentException("Malformed search template");
9193
}
9294
RestSearchAction.validateSearchRequest(restRequest, searchRequest);
93-
}
95+
},
96+
crossProjectEnabled
9497
);
9598
return multiRequest;
9699
}

modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.elasticsearch.rest.ServerlessScope;
2020
import org.elasticsearch.rest.action.RestToXContentListener;
2121
import org.elasticsearch.rest.action.search.RestSearchAction;
22+
import org.elasticsearch.search.crossproject.CrossProjectModeDecider;
2223
import org.elasticsearch.xcontent.XContentParser;
2324

2425
import java.io.IOException;
@@ -38,11 +39,11 @@ public class RestSearchTemplateAction extends BaseRestHandler {
3839
private static final Set<String> RESPONSE_PARAMS = Set.of(TYPED_KEYS_PARAM, RestSearchAction.TOTAL_HITS_AS_INT_PARAM);
3940

4041
private final Predicate<NodeFeature> clusterSupportsFeature;
41-
private final boolean crossProjectEnabled;
42+
private final CrossProjectModeDecider crossProjectModeDecider;
4243

4344
public RestSearchTemplateAction(Predicate<NodeFeature> clusterSupportsFeature, Settings settings) {
4445
this.clusterSupportsFeature = clusterSupportsFeature;
45-
this.crossProjectEnabled = settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false);
46+
this.crossProjectModeDecider = new CrossProjectModeDecider(settings);
4647
}
4748

4849
@Override
@@ -62,6 +63,7 @@ public String getName() {
6263

6364
@Override
6465
public RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
66+
boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
6567
if (crossProjectEnabled) {
6668
// accept but drop project_routing param until fully supported
6769
request.param("project_routing");

server/src/main/java/org/elasticsearch/rest/action/search/RestMultiSearchAction.java

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.elasticsearch.common.Strings;
1919
import org.elasticsearch.common.TriFunction;
2020
import org.elasticsearch.common.bytes.ReleasableBytesReference;
21+
import org.elasticsearch.common.logging.HeaderWarning;
2122
import org.elasticsearch.common.settings.Settings;
2223
import org.elasticsearch.core.Tuple;
2324
import org.elasticsearch.features.NodeFeature;
@@ -28,6 +29,7 @@
2829
import org.elasticsearch.rest.action.RestCancellableNodeClient;
2930
import org.elasticsearch.rest.action.RestRefCountedChunkedToXContentListener;
3031
import org.elasticsearch.search.builder.SearchSourceBuilder;
32+
import org.elasticsearch.search.crossproject.CrossProjectModeDecider;
3133
import org.elasticsearch.usage.SearchUsageHolder;
3234
import org.elasticsearch.xcontent.XContent;
3335
import org.elasticsearch.xcontent.XContentParser;
@@ -48,13 +50,15 @@ public class RestMultiSearchAction extends BaseRestHandler {
4850
private final boolean allowExplicitIndex;
4951
private final SearchUsageHolder searchUsageHolder;
5052
private final Predicate<NodeFeature> clusterSupportsFeature;
51-
private final Settings settings;
53+
private final CrossProjectModeDecider crossProjectModeDecider;
54+
private static final String MRT_ENABLED_IN_CPS_WARN = "ccs_minimize_roundtrips always defaults to true in Cross Project Search context."
55+
+ " Setting it explicitly has no effect irrespective of the value specified and is ignored.";
5256

5357
public RestMultiSearchAction(Settings settings, SearchUsageHolder searchUsageHolder, Predicate<NodeFeature> clusterSupportsFeature) {
54-
this.settings = settings;
5558
this.allowExplicitIndex = MULTI_ALLOW_EXPLICIT_INDEX.get(settings);
5659
this.searchUsageHolder = searchUsageHolder;
5760
this.clusterSupportsFeature = clusterSupportsFeature;
61+
this.crossProjectModeDecider = new CrossProjectModeDecider(settings);
5862
}
5963

6064
@Override
@@ -77,11 +81,18 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
7781
if (client.threadPool() != null && client.threadPool().getThreadContext() != null) {
7882
client.threadPool().getThreadContext().setErrorTraceTransportHeader(request);
7983
}
80-
if (settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false)) {
84+
boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
85+
if (crossProjectEnabled) {
8186
// accept but drop project_routing param until fully supported
8287
request.param("project_routing");
8388
}
84-
final MultiSearchRequest multiSearchRequest = parseRequest(request, allowExplicitIndex, searchUsageHolder, clusterSupportsFeature);
89+
final MultiSearchRequest multiSearchRequest = parseRequest(
90+
request,
91+
allowExplicitIndex,
92+
searchUsageHolder,
93+
clusterSupportsFeature,
94+
crossProjectEnabled
95+
);
8596
return channel -> {
8697
final RestCancellableNodeClient cancellableClient = new RestCancellableNodeClient(client, request.getHttpChannel());
8798
cancellableClient.execute(
@@ -99,9 +110,17 @@ public static MultiSearchRequest parseRequest(
99110
RestRequest restRequest,
100111
boolean allowExplicitIndex,
101112
SearchUsageHolder searchUsageHolder,
102-
Predicate<NodeFeature> clusterSupportsFeature
113+
Predicate<NodeFeature> clusterSupportsFeature,
114+
boolean crossProjectEnabled
103115
) throws IOException {
104-
return parseRequest(restRequest, allowExplicitIndex, searchUsageHolder, clusterSupportsFeature, (k, v, r) -> false);
116+
return parseRequest(
117+
restRequest,
118+
allowExplicitIndex,
119+
searchUsageHolder,
120+
clusterSupportsFeature,
121+
(k, v, r) -> false,
122+
crossProjectEnabled
123+
);
105124
}
106125

107126
/**
@@ -113,7 +132,8 @@ public static MultiSearchRequest parseRequest(
113132
boolean allowExplicitIndex,
114133
SearchUsageHolder searchUsageHolder,
115134
Predicate<NodeFeature> clusterSupportsFeature,
116-
TriFunction<String, Object, SearchRequest, Boolean> extraParamParser
135+
TriFunction<String, Object, SearchRequest, Boolean> extraParamParser,
136+
boolean crossProjectEnabled
117137
) throws IOException {
118138
MultiSearchRequest multiRequest = new MultiSearchRequest();
119139
IndicesOptions indicesOptions = IndicesOptions.fromRequest(restRequest, multiRequest.indicesOptions());
@@ -142,12 +162,10 @@ public static MultiSearchRequest parseRequest(
142162
if (searchRequest.pointInTimeBuilder() != null) {
143163
RestSearchAction.preparePointInTime(searchRequest, restRequest);
144164
} else {
145-
searchRequest.setCcsMinimizeRoundtrips(
146-
restRequest.paramAsBoolean("ccs_minimize_roundtrips", searchRequest.isCcsMinimizeRoundtrips())
147-
);
165+
searchRequest.setCcsMinimizeRoundtrips(maybeConsumeCcsMrtParam(restRequest, crossProjectEnabled));
148166
}
149167
multiRequest.add(searchRequest);
150-
}, extraParamParser);
168+
}, extraParamParser, crossProjectEnabled);
151169
List<SearchRequest> requests = multiRequest.requests();
152170
for (SearchRequest request : requests) {
153171
// preserve if it's set on the request
@@ -168,9 +186,10 @@ public static void parseMultiLineRequest(
168186
RestRequest request,
169187
IndicesOptions indicesOptions,
170188
boolean allowExplicitIndex,
171-
CheckedBiConsumer<SearchRequest, XContentParser, IOException> consumer
189+
CheckedBiConsumer<SearchRequest, XContentParser, IOException> consumer,
190+
boolean crossProjectEnabled
172191
) throws IOException {
173-
parseMultiLineRequest(request, indicesOptions, allowExplicitIndex, consumer, (k, v, r) -> false);
192+
parseMultiLineRequest(request, indicesOptions, allowExplicitIndex, consumer, (k, v, r) -> false, crossProjectEnabled);
174193
}
175194

176195
/**
@@ -182,12 +201,13 @@ public static void parseMultiLineRequest(
182201
IndicesOptions indicesOptions,
183202
boolean allowExplicitIndex,
184203
CheckedBiConsumer<SearchRequest, XContentParser, IOException> consumer,
185-
TriFunction<String, Object, SearchRequest, Boolean> extraParamParser
204+
TriFunction<String, Object, SearchRequest, Boolean> extraParamParser,
205+
boolean crossProjectEnabled
186206
) throws IOException {
187207

188208
String[] indices = Strings.splitStringByCommaToArray(request.param("index"));
189209
String searchType = request.param("search_type");
190-
boolean ccsMinimizeRoundtrips = request.paramAsBoolean("ccs_minimize_roundtrips", true);
210+
boolean ccsMinimizeRoundtrips = maybeConsumeCcsMrtParam(request, crossProjectEnabled);
191211
String routing = request.param("routing");
192212

193213
final Tuple<XContentType, ReleasableBytesReference> sourceTuple = request.contentOrSourceParam();
@@ -208,6 +228,26 @@ public static void parseMultiLineRequest(
208228
);
209229
}
210230

231+
private static boolean maybeConsumeCcsMrtParam(RestRequest request, boolean crossProjectEnabled) {
232+
if (crossProjectEnabled) {
233+
// Warn user, consume param, and return true.
234+
if (request.hasParam("ccs_minimize_roundtrips")) {
235+
HeaderWarning.addWarning(RestMultiSearchAction.MRT_ENABLED_IN_CPS_WARN);
236+
request.param("ccs_minimize_roundtrips");
237+
return true;
238+
}
239+
240+
/*
241+
* User has no preference, use the default value that's appropriate for CPS.
242+
* CPS searches should minimise round trips.
243+
*/
244+
return true;
245+
} else {
246+
// Not in CPS environment, pick whatever user chose.
247+
return request.paramAsBoolean("ccs_minimize_roundtrips", true);
248+
}
249+
}
250+
211251
@Override
212252
public boolean mediaTypesValid(RestRequest request) {
213253
return super.mediaTypesValid(request) && XContentType.supportsDelimitedBulkRequests(request.getXContentType());

server/src/test/java/org/elasticsearch/action/search/MultiSearchRequestTests.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void testFailWithUnknownKey() {
9898
).build();
9999
IllegalArgumentException ex = expectThrows(
100100
IllegalArgumentException.class,
101-
() -> RestMultiSearchAction.parseRequest(restRequest, true, new UsageService().getSearchUsageHolder(), nf -> false)
101+
() -> RestMultiSearchAction.parseRequest(restRequest, true, new UsageService().getSearchUsageHolder(), nf -> false, false)
102102
);
103103
assertEquals("key [unknown_key] is not supported in the metadata section", ex.getMessage());
104104
}
@@ -116,7 +116,8 @@ public void testSimpleAddWithCarriageReturn() throws Exception {
116116
restRequest,
117117
true,
118118
new UsageService().getSearchUsageHolder(),
119-
nf -> false
119+
nf -> false,
120+
false
120121
);
121122
assertThat(request.requests().size(), equalTo(1));
122123
assertThat(request.requests().get(0).indices()[0], equalTo("test"));
@@ -139,7 +140,8 @@ public void testDefaultIndicesOptions() throws IOException {
139140
restRequest,
140141
true,
141142
new UsageService().getSearchUsageHolder(),
142-
nf -> false
143+
nf -> false,
144+
false
143145
);
144146
assertThat(request.requests().size(), equalTo(1));
145147
assertThat(request.requests().get(0).indices()[0], equalTo("test"));
@@ -249,7 +251,7 @@ public void testMsearchTerminatedByNewline() throws Exception {
249251
).build();
250252
IllegalArgumentException expectThrows = expectThrows(
251253
IllegalArgumentException.class,
252-
() -> RestMultiSearchAction.parseRequest(restRequest, true, new UsageService().getSearchUsageHolder(), nf -> false)
254+
() -> RestMultiSearchAction.parseRequest(restRequest, true, new UsageService().getSearchUsageHolder(), nf -> false, false)
253255
);
254256
assertEquals("The msearch request must be terminated by a newline [\n]", expectThrows.getMessage());
255257

@@ -262,7 +264,8 @@ public void testMsearchTerminatedByNewline() throws Exception {
262264
restRequestWithNewLine,
263265
true,
264266
new UsageService().getSearchUsageHolder(),
265-
nf -> false
267+
nf -> false,
268+
false
266269
);
267270
assertEquals(3, msearchRequest.requests().size());
268271
}
@@ -283,7 +286,7 @@ private MultiSearchRequest parseMultiSearchRequest(RestRequest restRequest) thro
283286
new SearchSourceBuilder().parseXContent(parser, false, new UsageService().getSearchUsageHolder(), nf -> false)
284287
);
285288
request.add(searchRequest);
286-
});
289+
}, false);
287290
return request;
288291
}
289292

x-pack/plugin/eql/src/main/java/org/elasticsearch/xpack/eql/plugin/RestEqlSearchAction.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.action.support.IndicesOptions;
1111
import org.elasticsearch.client.internal.node.NodeClient;
1212
import org.elasticsearch.common.Strings;
13+
import org.elasticsearch.common.logging.HeaderWarning;
1314
import org.elasticsearch.common.settings.Settings;
1415
import org.elasticsearch.index.IndexNotFoundException;
1516
import org.elasticsearch.logging.LogManager;
@@ -21,6 +22,7 @@
2122
import org.elasticsearch.rest.Scope;
2223
import org.elasticsearch.rest.ServerlessScope;
2324
import org.elasticsearch.rest.action.RestCancellableNodeClient;
25+
import org.elasticsearch.search.crossproject.CrossProjectModeDecider;
2426
import org.elasticsearch.xcontent.XContentBuilder;
2527
import org.elasticsearch.xcontent.XContentParser;
2628
import org.elasticsearch.xcontent.XContentType;
@@ -40,10 +42,10 @@
4042
public class RestEqlSearchAction extends BaseRestHandler {
4143
private static final Logger LOGGER = LogManager.getLogger(RestEqlSearchAction.class);
4244
private static final String SEARCH_PATH = "/{index}/_eql/search";
43-
private final Settings settings;
45+
private final CrossProjectModeDecider crossProjectModeDecider;
4446

4547
public RestEqlSearchAction(Settings settings) {
46-
this.settings = settings;
48+
this.crossProjectModeDecider = new CrossProjectModeDecider(settings);
4749
}
4850

4951
@Override
@@ -53,7 +55,8 @@ public List<Route> routes() {
5355

5456
@Override
5557
protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient client) throws IOException {
56-
if (settings != null && settings.getAsBoolean("serverless.cross_project.enabled", false)) {
58+
boolean crossProjectEnabled = crossProjectModeDecider.crossProjectEnabled();
59+
if (crossProjectEnabled) {
5760
// accept but drop project_routing param until fully supported
5861
request.param("project_routing");
5962
}
@@ -74,7 +77,23 @@ protected RestChannelConsumer prepareRequest(RestRequest request, NodeClient cli
7477
eqlRequest.keepAlive(request.paramAsTime("keep_alive", eqlRequest.keepAlive()));
7578
}
7679
eqlRequest.keepOnCompletion(request.paramAsBoolean("keep_on_completion", eqlRequest.keepOnCompletion()));
77-
eqlRequest.ccsMinimizeRoundtrips(request.paramAsBoolean("ccs_minimize_roundtrips", eqlRequest.ccsMinimizeRoundtrips()));
80+
if (crossProjectEnabled) {
81+
if (request.hasParam("ccs_minimize_roundtrips")) {
82+
/*
83+
* MRT should not be settable by the user in Cross Project Search environment.
84+
* Irrespective of the value, issue a warning, and set MRT to true for the request.
85+
*
86+
* By default, MRT is true and is picked up from RequestDefaults.CCS_MINIMIZE_ROUNDTRIPS.
87+
*/
88+
String warning = "ccs_minimize_roundtrips always defaults to true in Cross Project Search context."
89+
+ " Setting it explicitly has no effect irrespective of the value specified and is ignored.";
90+
HeaderWarning.addWarning(warning);
91+
request.param("ccs_minimize_roundtrips");
92+
eqlRequest.ccsMinimizeRoundtrips(true);
93+
}
94+
} else {
95+
eqlRequest.ccsMinimizeRoundtrips(request.paramAsBoolean("ccs_minimize_roundtrips", eqlRequest.ccsMinimizeRoundtrips()));
96+
}
7897
eqlRequest.allowPartialSearchResults(
7998
request.paramAsBoolean("allow_partial_search_results", eqlRequest.allowPartialSearchResults())
8099
);

0 commit comments

Comments
 (0)