4444import java .util .Arrays ;
4545import java .util .List ;
4646import java .util .Locale ;
47+ import java .util .Optional ;
4748import java .util .Set ;
4849import java .util .function .IntConsumer ;
4950import java .util .function .Predicate ;
@@ -68,13 +69,11 @@ public class RestSearchAction extends BaseRestHandler {
6869
6970 private final SearchUsageHolder searchUsageHolder ;
7071 private final Predicate <NodeFeature > clusterSupportsFeature ;
71- private final Settings settings ;
7272 private final CrossProjectModeDecider crossProjectModeDecider ;
7373
7474 public RestSearchAction (SearchUsageHolder searchUsageHolder , Predicate <NodeFeature > clusterSupportsFeature , Settings settings ) {
7575 this .searchUsageHolder = searchUsageHolder ;
7676 this .clusterSupportsFeature = clusterSupportsFeature ;
77- this .settings = settings ;
7877 this .crossProjectModeDecider = new CrossProjectModeDecider (settings );
7978 }
8079
@@ -134,7 +133,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
134133 clusterSupportsFeature ,
135134 setSize ,
136135 searchUsageHolder ,
137- crossProjectEnabled
136+ Optional . of ( crossProjectEnabled )
138137 )
139138 );
140139
@@ -146,7 +145,9 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
146145
147146 /**
148147 * Parses the rest request on top of the SearchRequest, preserving values that are not overridden by the rest request.
149- *
148+ * The endpoint calling this method is treated as if it does not support Cross Project Search (CPS). In case it supports
149+ * CPS, it should call in the other appropriate overload and pass in the CPS state explicitly either via Optional.of(true)
150+ * or Optional.of(false).
150151 * @param searchRequest the search request that will hold what gets parsed
151152 * @param request the rest request to read from
152153 * @param requestContentParser body of the request to read. This method does not attempt to read the body from the {@code request}
@@ -172,7 +173,15 @@ public static void parseSearchRequest(
172173 IntConsumer setSize ,
173174 @ Nullable SearchUsageHolder searchUsageHolder
174175 ) throws IOException {
175- parseSearchRequest (searchRequest , request , requestContentParser , clusterSupportsFeature , setSize , searchUsageHolder , false );
176+ parseSearchRequest (
177+ searchRequest ,
178+ request ,
179+ requestContentParser ,
180+ clusterSupportsFeature ,
181+ setSize ,
182+ searchUsageHolder ,
183+ Optional .empty ()
184+ );
176185 }
177186
178187 /**
@@ -185,7 +194,10 @@ public static void parseSearchRequest(
185194 * @param clusterSupportsFeature used to check if certain features are available in this cluster
186195 * @param setSize how the size url parameter is handled. {@code udpate_by_query} and regular search differ here.
187196 * @param searchUsageHolder the holder of search usage stats
188- * @param crossProjectEnabled whether serverless.cross_project.enabled is set to true
197+ * @param crossProjectEnabled Specifies the state of Cross Project Search (CPS) for the endpoint that's calling this method.
198+ * Optional.of(true) - signifies that the endpoint supports CPS,
199+ * Optional.of(false) - signifies that the endpoint supports CPS but CPS is disabled, and,
200+ * Optional.empty() - signifies that the endpoint does not support CPS.
189201 */
190202 public static void parseSearchRequest (
191203 SearchRequest searchRequest ,
@@ -194,7 +206,7 @@ public static void parseSearchRequest(
194206 Predicate <NodeFeature > clusterSupportsFeature ,
195207 IntConsumer setSize ,
196208 @ Nullable SearchUsageHolder searchUsageHolder ,
197- boolean crossProjectEnabled
209+ Optional < Boolean > crossProjectEnabled
198210 ) throws IOException {
199211 if (searchRequest .source () == null ) {
200212 searchRequest .source (new SearchSourceBuilder ());
@@ -205,7 +217,7 @@ public static void parseSearchRequest(
205217 * We only do it if in a Cross Project Environment, though, because outside it, such details are not
206218 * expected and valid.
207219 */
208- SearchRequest searchRequestForParsing = crossProjectEnabled ? searchRequest : null ;
220+ SearchRequest searchRequestForParsing = crossProjectEnabled . orElse ( false ) ? searchRequest : null ;
209221 if (requestContentParser != null ) {
210222 if (searchUsageHolder == null ) {
211223 searchRequest .source ().parseXContent (searchRequestForParsing , requestContentParser , true , clusterSupportsFeature );
@@ -250,7 +262,7 @@ public static void parseSearchRequest(
250262 searchRequest .routing (request .param ("routing" ));
251263 searchRequest .preference (request .param ("preference" ));
252264 IndicesOptions indicesOptions = IndicesOptions .fromRequest (request , searchRequest .indicesOptions ());
253- if (crossProjectEnabled && searchRequest .allowsCrossProject () && searchRequest .pointInTimeBuilder () == null ) {
265+ if (crossProjectEnabled . orElse ( false ) && searchRequest .allowsCrossProject () && searchRequest .pointInTimeBuilder () == null ) {
254266 indicesOptions = IndicesOptions .builder (indicesOptions )
255267 .crossProjectModeOptions (new IndicesOptions .CrossProjectModeOptions (true ))
256268 .build ();
@@ -262,9 +274,30 @@ public static void parseSearchRequest(
262274 if (searchRequest .pointInTimeBuilder () != null ) {
263275 preparePointInTime (searchRequest , request );
264276 } else {
265- searchRequest .setCcsMinimizeRoundtrips (
266- request .paramAsBoolean ("ccs_minimize_roundtrips" , searchRequest .isCcsMinimizeRoundtrips ())
267- );
277+ if (crossProjectEnabled .orElse (false )) {
278+ /*
279+ * MRT should not be settable by the user when in Cross Project Search environment.
280+ * Only _async_search uses MRT=false. However, in RestSubmitAsyncSearchAction, we
281+ * already, explicitly, and directly call in `SearchRequest#setCcsMinimizeRoundtrips()`
282+ * to set it to true. Although other searches that utilise SearchRequest-s do not call
283+ * this method, SearchRequest, by default, sets MRT to true when it is instantiated.
284+ * This way, all searches pivot to MRT=true for CPS.
285+ *
286+ * Since users will anyway see a banner via Kibana that setting MRT in Serverless has no
287+ * effect, we can safely drop it.
288+ */
289+ if (request .hasParam ("ccs_minimize_roundtrips" )) {
290+ request .param ("ccs_minimize_roundtrips" );
291+ }
292+ } else {
293+ /*
294+ * Either we're not in a Cross Project Search environment or the endpoint isn't compatible with it. Parse what's in the
295+ * request.
296+ */
297+ searchRequest .setCcsMinimizeRoundtrips (
298+ request .paramAsBoolean ("ccs_minimize_roundtrips" , searchRequest .isCcsMinimizeRoundtrips ())
299+ );
300+ }
268301 }
269302 if (request .paramAsBoolean ("force_synthetic_source" , false )) {
270303 searchRequest .setForceSyntheticSource (true );
0 commit comments