This is an automated email from the ASF dual-hosted git repository.
janhoy pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new f567b7b1a94 SOLR-18419: Simplify PingRequestHandler shard handling
(#4890)
f567b7b1a94 is described below
commit f567b7b1a9415c8bfcf3f64ddb51aa78eb007a8f
Author: Jan Høydahl <[email protected]>
AuthorDate: Wed Sep 9 09:00:25 2026 +0200
SOLR-18419: Simplify PingRequestHandler shard handling (#4890)
---
.../SOLR-18419-ping-delegate-handler.yml | 7 ++
.../apache/solr/handler/PingRequestHandler.java | 103 ++++++++++-----------
.../handler/PingRequestHandlerParamSetTest.java | 49 ++++++++++
.../solr/handler/PingRequestHandlerTest.java | 44 +++++++++
4 files changed, 150 insertions(+), 53 deletions(-)
diff --git a/changelog/unreleased/SOLR-18419-ping-delegate-handler.yml
b/changelog/unreleased/SOLR-18419-ping-delegate-handler.yml
new file mode 100644
index 00000000000..08672defd7f
--- /dev/null
+++ b/changelog/unreleased/SOLR-18419-ping-delegate-handler.yml
@@ -0,0 +1,7 @@
+title: Simplify PingRequestHandler shard handling
+type: changed
+authors:
+ - name: Jan Høydahl
+links:
+ - name: SOLR-18419
+ url: https://issues.apache.org/jira/browse/SOLR-18419
diff --git a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
index ee49eed153d..8333ab3c0f5 100644
--- a/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/PingRequestHandler.java
@@ -20,6 +20,7 @@ import static
org.apache.solr.common.params.CommonParams.ACTION;
import static org.apache.solr.common.params.CommonParams.DISABLE;
import static org.apache.solr.common.params.CommonParams.DISTRIB;
import static org.apache.solr.common.params.CommonParams.ENABLE;
+import static org.apache.solr.core.RequestParams.USEPARAM;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
@@ -34,11 +35,13 @@ import org.apache.solr.common.params.ModifiableSolrParams;
import org.apache.solr.common.params.ShardParams;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;
+import org.apache.solr.util.SolrPluginUtils;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,8 +60,8 @@ import org.slf4j.LoggerFactory;
* responses (or for a simple connection failure) to know if there is a
problem with the Solr
* server.
*
- * <p>Note in case isShard=true, PingRequestHandler respond back with what the
delegated handler
- * returns (by default it's /select handler).
+ * <p>A distributed ping is fanned out to the delegated handler on each shard
(by default the
+ * /select handler).
*
* <pre class="prettyprint">
* <requestHandler name="/admin/ping" class="solr.PingRequestHandler">
@@ -229,73 +232,67 @@ public class PingRequestHandler extends
RequestHandlerBase implements SolrCoreAw
protected void handlePing(SolrQueryRequest req, SolrQueryResponse rsp)
throws Exception {
- SolrParams params = req.getParams();
SolrCore core = req.getCore();
- // Get the RequestHandler
- String qt = params.get(CommonParams.QT); // optional; you get the default
otherwise
+ SolrParams configParams = resolveConfiguredParams(req);
+ String qt = configParams.get(CommonParams.QT);
SolrRequestHandler handler = core.getRequestHandler(qt);
if (handler == null) {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST, "Unknown RequestHandler (qt): "
+ qt);
}
-
if (handler instanceof PingRequestHandler) {
- // In case it's a query for shard, use default handler
- if (params.getBool(ShardParams.IS_SHARD, false)) {
- handler = core.getRequestHandler(null);
- ModifiableSolrParams wparams = new ModifiableSolrParams(params);
- wparams.remove(CommonParams.QT);
- req.setParams(wparams);
- } else {
- throw new SolrException(
- SolrException.ErrorCode.BAD_REQUEST,
- "Cannot execute the PingRequestHandler recursively");
- }
+ throw new SolrException(
+ SolrException.ErrorCode.BAD_REQUEST, "Cannot execute the
PingRequestHandler recursively");
+ }
+
+ ModifiableSolrParams overrides = new ModifiableSolrParams();
+ boolean distrib = req.getParams().getBool(DISTRIB, false);
+ overrides.set(DISTRIB, distrib);
+ if (distrib) {
+ // target the delegate on each shard, not this ping handler
+ overrides.set(ShardParams.SHARDS_QT, qt == null ? "/select" : qt);
}
// Execute the ping query and catch any possible exception
Throwable ex = null;
-
- // In case it's a query for shard, return the result from delegated
handler for distributed
- // query to merge result
- if (params.getBool(ShardParams.IS_SHARD, false)) {
- try {
- core.execute(handler, req, rsp);
- ex = rsp.getException();
- } catch (Exception e) {
- ex = e;
+ try (SolrQueryRequest pingReq =
+ req.subRequest(SolrParams.wrapDefaults(overrides, configParams))) {
+ SolrQueryResponse pingrsp = new SolrQueryResponse();
+ core.execute(handler, pingReq, pingrsp);
+ ex = pingrsp.getException();
+ NamedList<Object> headers = rsp.getResponseHeader();
+ if (headers != null) {
+ headers.add("zkConnected",
pingrsp.getResponseHeader().get("zkConnected"));
}
- // Send an error or return
- if (ex != null) {
- throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR,
- "Ping query caused exception: " + ex.getMessage(),
- ex);
- }
- } else {
- try {
- SolrQueryResponse pingrsp = new SolrQueryResponse();
- core.execute(handler, req, pingrsp);
- ex = pingrsp.getException();
- NamedList<Object> headers = rsp.getResponseHeader();
- if (headers != null) {
- headers.add("zkConnected",
pingrsp.getResponseHeader().get("zkConnected"));
- }
+ } catch (Exception e) {
+ ex = e;
+ }
- } catch (Exception e) {
- ex = e;
- }
+ // Send an error or an 'OK' message (response code will be 200)
+ if (ex != null) {
+ throw new SolrException(
+ SolrException.ErrorCode.SERVER_ERROR,
+ "Ping query caused exception: " + ex.getMessage(),
+ ex);
+ }
- // Send an error or an 'OK' message (response code will be 200)
- if (ex != null) {
- throw new SolrException(
- SolrException.ErrorCode.SERVER_ERROR,
- "Ping query caused exception: " + ex.getMessage(),
- ex);
- }
+ rsp.add("status", "OK");
+ }
- rsp.add("status", "OK");
+ /**
+ * Resolves this handler's configured invariants, appends, defaults and
{@code useParams}
+ * paramsets into a single {@link SolrParams}. The delegate handler is named
by {@code qt}; a null
+ * {@code qt} means the core's default handler.
+ */
+ private SolrParams resolveConfiguredParams(SolrQueryRequest req) {
+ try (SolrQueryRequest configOnly = req.subRequest(new
ModifiableSolrParams())) {
+ PluginInfo info = getPluginInfo();
+ if (info != null && info.attributes.containsKey(USEPARAM)) {
+ configOnly.getContext().put(USEPARAM, info.attributes.get(USEPARAM));
+ }
+ SolrPluginUtils.setDefaults(configOnly, defaults, appends, invariants);
+ return configOnly.getParams();
}
}
diff --git
a/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerParamSetTest.java
b/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerParamSetTest.java
new file mode 100644
index 00000000000..0368bc39cbc
--- /dev/null
+++
b/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerParamSetTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.handler;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import org.apache.commons.io.file.PathUtils;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.SolrException;
+import org.junit.BeforeClass;
+
+/**
+ * The implicit {@code /admin/ping} handler declares {@code
useParams=_ADMIN_PING}, so the handler
+ * it delegates to may also be configured through a paramset in {@code
params.json}.
+ */
+public class PingRequestHandlerParamSetTest extends SolrTestCaseJ4 {
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ Path solrHome = createTempDir();
+ PathUtils.copyDirectory(TEST_HOME(), solrHome,
StandardCopyOption.COPY_ATTRIBUTES);
+ Files.writeString(
+ solrHome.resolve("collection1").resolve("conf").resolve("params.json"),
+
"{\"params\":{\"_ADMIN_PING\":{\"_invariants_\":{\"qt\":\"/nosuchhandler\"}}}}");
+ initCore("solrconfig.xml", "schema.xml", solrHome);
+ }
+
+ public void testDelegateHandlerFromParamSet() {
+ SolrException se =
+ expectThrows(SolrException.class, () -> h.query("/admin/ping",
req("qt", "/select")));
+ assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, se.code());
+ assertTrue(se.getMessage(), se.getMessage().contains("/nosuchhandler"));
+ }
+}
diff --git
a/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerTest.java
b/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerTest.java
index 3f151e51efc..d676c007cad 100644
--- a/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/PingRequestHandlerTest.java
@@ -29,6 +29,7 @@ import org.apache.solr.client.solrj.response.SolrPingResponse;
import org.apache.solr.cloud.MiniSolrCloudCluster;
import org.apache.solr.cloud.SolrCloudTestCase;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.embedded.JettyConfig;
import org.apache.solr.embedded.JettySolrRunner;
@@ -166,6 +167,40 @@ public class PingRequestHandlerTest extends SolrTestCaseJ4
{
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, se.code());
}
+ public void testDelegateHandlerFromConfig() throws Exception {
+ // with no qt configured, ping delegates to the default handler
+ handler = new PingRequestHandler();
+ handler.init(new NamedList<>());
+ handler.inform(h.getCore());
+ SolrQueryResponse rsp = makeRequest(handler, req("qt", "/nosuchhandler"));
+ assertEquals("OK", rsp.getValues().get("status"));
+
+ // ping returns a plain status, not the delegate's response
+ rsp = makeRequest(handler, req("isShard", "true", "fl", "id"));
+ assertEquals("OK", rsp.getValues().get("status"));
+ assertNull(rsp.getValues().get("response"));
+
+ // a qt configured as an invariant selects the delegate
+ handler = new PingRequestHandler();
+ NamedList<Object> initParams = new NamedList<>();
+ NamedList<String> invariants = new NamedList<>();
+ invariants.add("qt", "/nosuchhandler");
+ initParams.add("invariants", invariants);
+ handler.init(initParams);
+ handler.inform(h.getCore());
+ SolrException se =
+ expectThrows(SolrException.class, () -> makeRequest(handler, req("qt",
"/select")));
+ assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, se.code());
+ }
+
+ public void testPingUsesConfiguredQuery() throws Exception {
+ // the ping runs its configured query; stray request params do not change
it (an unparseable
+ // rows or an unknown handler would otherwise make the delegate fail)
+ String response = h.query("/admin/ping", req("qt", "/nosuchhandler",
"rows", "notanumber"));
+ assertTrue(response, response.contains("<str name=\"status\">OK</str>"));
+ assertFalse(response, response.contains("name=\"response\""));
+ }
+
public void testPingInClusterWithNoHealthCheck() throws Exception {
MiniSolrCloudCluster miniCluster =
@@ -203,6 +238,15 @@ public class PingRequestHandlerTest extends SolrTestCaseJ4
{
assertEquals(0, rsp.getStatus());
assertTrue(rsp.getResponseHeader().getBooleanArg(("zkConnected")));
+ // a request qt cannot redirect the shard requests back into the ping
handler
+ SolrPingWithDistrib reqRecursive = new SolrPingWithDistrib();
+ reqRecursive.setDistrib(true);
+ reqRecursive.getParams().add(CommonParams.QT, "/admin/ping");
+ rsp = reqRecursive.process(cloudSolrClient, collectionName);
+ assertEquals(0, rsp.getStatus());
+ assertEquals("OK", rsp.getResponse().get("status"));
+ assertNull(rsp.getResponse().get("response"));
+
} finally {
miniCluster.shutdown();
}