This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch branch_9x
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 2f11d3d5525c753261322546cb09d464ffb5888e
Author: David Smiley <[email protected]>
AuthorDate: Tue Dec 16 23:56:34 2025 -0500

    SOLR-17982: setForcedDistrib (#3931)
    
    Provide an internal API to force distributed search (even when one shard).
    
    (cherry picked from commit 5c9cab2901a88385a09ca2a17821e41f062731c3)
---
 .../SOLR-17982-refactorSearchHandlerForcedDistrib.yml      |  9 +++++++++
 .../apache/solr/handler/component/HttpShardHandler.java    |  8 ++++++--
 .../org/apache/solr/handler/component/ResponseBuilder.java | 10 ++++++++++
 .../org/apache/solr/handler/component/SearchHandler.java   |  6 +++---
 .../src/java/org/apache/solr/servlet/HttpSolrCall.java     | 14 ++++++++++++++
 .../org/apache/solr/BaseDistributedSearchTestCase.java     | 11 +++++------
 6 files changed, 47 insertions(+), 11 deletions(-)

diff --git 
a/changelog/unreleased/SOLR-17982-refactorSearchHandlerForcedDistrib.yml 
b/changelog/unreleased/SOLR-17982-refactorSearchHandlerForcedDistrib.yml
new file mode 100644
index 00000000000..dd330bd13f4
--- /dev/null
+++ b/changelog/unreleased/SOLR-17982-refactorSearchHandlerForcedDistrib.yml
@@ -0,0 +1,9 @@
+# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
+title: Provide an internal API to force distributed search (even when one 
shard). Also, refactor/reorganize SearchHandler for clarity & extensibility.
+type: other # added, changed, fixed, deprecated, removed, dependency_update, 
security, other
+authors:
+  - name: David Smiley
+  - name: Sonu Sharma
+links:
+  - name: SOLR-17982
+    url: https://issues.apache.org/jira/browse/SOLR-17982
diff --git 
a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java 
b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
index 36c62aae972..73b960db91e 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
@@ -406,7 +406,7 @@ public class HttpShardHandler extends ShardHandler {
   public void prepDistributed(ResponseBuilder rb) {
     final SolrQueryRequest req = rb.req;
     final SolrParams params = req.getParams();
-    final String shards = params.get(ShardParams.SHARDS);
+    String shards = params.get(ShardParams.SHARDS);
 
     CoreDescriptor coreDescriptor = req.getCore().getCoreDescriptor();
     CloudDescriptor cloudDescriptor = req.getCloudDescriptor();
@@ -445,7 +445,7 @@ public class HttpShardHandler extends ShardHandler {
               .build();
       rb.slices = replicaSource.getSliceNames().toArray(new 
String[replicaSource.getSliceCount()]);
 
-      if (canShortCircuit(rb.slices, onlyNrt, params, cloudDescriptor)) {
+      if (!rb.isForcedDistrib() && canShortCircuit(rb.slices, onlyNrt, params, 
cloudDescriptor)) {
         rb.isDistrib = false;
         rb.shortCircuitedURL =
             ZkCoreNodeProps.getCoreUrl(zkController.getBaseUrl(), 
coreDescriptor.getName());
@@ -477,6 +477,9 @@ public class HttpShardHandler extends ShardHandler {
         }
       }
     } else {
+      if (shards == null) {
+        shards = req.getHttpSolrCall().getThisNodeUrl() + "/" + 
req.getCore().getName();
+      }
       replicaSource =
           new StandaloneReplicaSource.Builder()
               .allowListUrlChecker(urlChecker)
@@ -504,6 +507,7 @@ public class HttpShardHandler extends ShardHandler {
     return String.join("|", shardUrls);
   }
 
+  /** Can we avoid distributed search / coordinator? */
   private boolean canShortCircuit(
       String[] slices,
       boolean onlyNrtReplicas,
diff --git 
a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java 
b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
index 7ce3e1c05c9..4547438689e 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ResponseBuilder.java
@@ -151,6 +151,16 @@ public class ResponseBuilder {
   public List<ShardRequest> outgoing; // requests to be sent
   public List<ShardRequest> finished; // requests that have received responses 
from all shards
   public String shortCircuitedURL;
+  private boolean forcedDistrib = false;
+
+  public boolean isForcedDistrib() {
+    return forcedDistrib;
+  }
+
+  /** Force distributed-search / coordinator logic when not a sub-shard 
request. */
+  public void setForcedDistrib(boolean forcedDistrib) {
+    this.forcedDistrib = forcedDistrib;
+  }
 
   /** This function will return true if this was a distributed search request. 
*/
   public boolean isDistributed() {
diff --git 
a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java 
b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
index 0bf03caab5e..10ef832d924 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java
@@ -334,8 +334,8 @@ public class SearchHandler extends RequestHandlerBase
   }
 
   protected boolean isDistrib(SolrQueryRequest req, ResponseBuilder rb) {
-    boolean isZkAware = req.getCoreContainer().isZooKeeperAware();
-    boolean isDistrib = req.getParams().getBool(DISTRIB, isZkAware);
+    boolean theDefault = req.getCoreContainer().isZooKeeperAware() || 
rb.isForcedDistrib();
+    boolean isDistrib = req.getParams().getBool(DISTRIB, theDefault);
     if (!isDistrib) {
       // for back compat, a shards param with URLs like localhost:8983/solr 
will mean that this
       // search is distributed.
@@ -345,7 +345,7 @@ public class SearchHandler extends RequestHandlerBase
     return isDistrib;
   }
 
-  public ShardHandler getAndPrepShardHandler(SolrQueryRequest req, 
ResponseBuilder rb) {
+  protected ShardHandler getAndPrepShardHandler(SolrQueryRequest req, 
ResponseBuilder rb) {
     ShardHandler shardHandler = null;
 
     CoreContainer cc = req.getCoreContainer();
diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java 
b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
index 9f4696e7740..93feb4b5d15 100644
--- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
+++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java
@@ -82,6 +82,7 @@ import org.apache.solr.api.V2HttpCall;
 import org.apache.solr.client.api.util.SolrVersion;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.cloud.ZkController;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.Aliases;
@@ -1343,6 +1344,19 @@ public class HttpSolrCall {
     return Collections.emptyMap();
   }
 
+  /**
+   * The URL to this core, e.g. {@code http://localhost:8983/solr}.
+   *
+   * @see ZkController#getBaseUrl()
+   */
+  public String getThisNodeUrl() {
+    String scheme = getReq().getScheme();
+    String host = getReq().getServerName();
+    int port = getReq().getServerPort();
+    String context = getReq().getContextPath();
+    return String.format(Locale.ROOT, "%s://%s:%d%s", scheme, host, port, 
context);
+  }
+
   /** A faster method for randomly picking items when you do not need to 
consume all items. */
   private static class RandomIterator<E> implements Iterator<E> {
     private Random rand;
diff --git 
a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
 
b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 2766781708e..fbc1c26069c 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -711,19 +711,18 @@ public abstract class BaseDistributedSearchTestCase 
extends SolrTestCaseJ4 {
 
   /** Returns the QueryResponse from {@link #queryServer} */
   protected QueryResponse query(boolean setDistribParams, SolrParams p) throws 
Exception {
+    if (p.get("distrib") != null) {
+      throw new IllegalArgumentException("don't pass distrib param");
+    }
 
-    final ModifiableSolrParams params = new ModifiableSolrParams(p);
-
-    // TODO: look into why passing true causes fails
-    params.set("distrib", "false");
-    final QueryResponse controlRsp = controlClient.query(params);
+    final QueryResponse controlRsp = controlClient.query(p);
     validateControlData(controlRsp);
 
     if (shardCount == 0) { // mostly for temp debugging
       return controlRsp;
     }
 
-    params.remove("distrib");
+    final ModifiableSolrParams params = new ModifiableSolrParams(p);
     if (setDistribParams) setDistributedParams(params);
 
     QueryResponse rsp = queryServer(params);

Reply via email to