You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ds...@apache.org on 2023/11/30 15:20:14 UTC

(solr) branch main updated: SOLR-17053: If all shards fail, fail the request despite shards.tolerant (#2102)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new c1a3fd3a474 SOLR-17053: If all shards fail, fail the request despite shards.tolerant (#2102)
c1a3fd3a474 is described below

commit c1a3fd3a47475c5d3ff5da323ba8c41c5fb76283
Author: aparnasuresh85 <ap...@salesforce.com>
AuthorDate: Thu Nov 30 10:20:06 2023 -0500

    SOLR-17053: If all shards fail, fail the request despite shards.tolerant (#2102)
---
 solr/CHANGES.txt                                   |  2 ++
 .../solr/handler/component/SearchHandler.java      | 20 +++++++++--
 .../test/org/apache/solr/TestTolerantSearch.java   | 40 ++++++++++++++++++++++
 3 files changed, 59 insertions(+), 3 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index bb45bd51605..be5eb556f9c 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -87,6 +87,8 @@ New Features
 
 Improvements
 ---------------------
+* SOLR-17053: Distributed search with shards.tolerant: if all shards fail, fail the request (Aparna Suresh via David Smiley)
+
 * SOLR-16924: RESTORECORE now sets the UpdateLog to ACTIVE state instead of requiring a separate
   REQUESTAPPLYUPDATES call in Collection restore.  (Julia Lamoine, David Smiley)
 
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 6f831f67714..2c7f9924436 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
@@ -587,9 +587,23 @@ public class SearchHandler extends RequestHandlerBase
                       SolrException.ErrorCode.SERVER_ERROR, srsp.getException());
                 }
               } else {
-                rsp.getResponseHeader()
-                    .asShallowMap()
-                    .put(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
+                // Check if the purpose includes 'PURPOSE_GET_TOP_IDS'
+                boolean includesTopIdsPurpose =
+                    (srsp.getShardRequest().purpose & ShardRequest.PURPOSE_GET_TOP_IDS) != 0;
+                // Check if all responses have exceptions
+                boolean allResponsesHaveExceptions =
+                    srsp.getShardRequest().responses.stream()
+                        .allMatch(response -> response.getException() != null);
+                // Check if all shards have failed for PURPOSE_GET_TOP_IDS
+                boolean allShardsFailed = includesTopIdsPurpose && allResponsesHaveExceptions;
+                // if all shards fail, fail the request despite shards.tolerant
+                if (allShardsFailed) {
+                  throw (SolrException) srsp.getException();
+                } else {
+                  rsp.getResponseHeader()
+                      .asShallowMap()
+                      .put(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY, Boolean.TRUE);
+                }
               }
             }
 
diff --git a/solr/core/src/test/org/apache/solr/TestTolerantSearch.java b/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
index 29658475281..fe4887aebea 100644
--- a/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
@@ -117,6 +117,7 @@ public class TestTolerantSearch extends SolrJettyTestBase {
   public void testGetFieldsPhaseError() throws SolrServerException, IOException {
     BadResponseWriter.failOnGetFields = true;
     BadResponseWriter.failOnGetTopIds = false;
+    BadResponseWriter.failAllShards = false;
     SolrQuery query = new SolrQuery();
     query.setQuery("subject:batman OR subject:superman");
     query.addField("id");
@@ -166,6 +167,7 @@ public class TestTolerantSearch extends SolrJettyTestBase {
   public void testGetTopIdsPhaseError() throws SolrServerException, IOException {
     BadResponseWriter.failOnGetTopIds = true;
     BadResponseWriter.failOnGetFields = false;
+    BadResponseWriter.failAllShards = false;
     SolrQuery query = new SolrQuery();
     query.setQuery("subject:batman OR subject:superman");
     query.addField("id");
@@ -212,10 +214,44 @@ public class TestTolerantSearch extends SolrJettyTestBase {
     unIgnoreException("Dummy exception in BadResponseWriter");
   }
 
+  @SuppressWarnings("unchecked")
+  public void testAllShardsFail() throws SolrServerException, IOException {
+    BadResponseWriter.failOnGetTopIds = false;
+    BadResponseWriter.failOnGetFields = false;
+    BadResponseWriter.failAllShards = true;
+    SolrQuery query = new SolrQuery();
+    query.setQuery("subject:batman OR subject:superman");
+    query.addField("id");
+    query.addField("subject");
+    query.set("distrib", "true");
+    query.set("shards", shard1 + "," + shard2);
+    query.set(ShardParams.SHARDS_INFO, "true");
+    query.set("debug", "true");
+    query.set("stats", "true");
+    query.set("stats.field", "id");
+    query.set("mlt", "true");
+    query.set("mlt.fl", "title");
+    query.set("mlt.count", "1");
+    query.set("mlt.mintf", "0");
+    query.set("mlt.mindf", "0");
+    query.setHighlight(true);
+    query.addFacetField("id");
+    query.setFacet(true);
+
+    ignoreException("Dummy exception in BadResponseWriter");
+
+    expectThrows(SolrException.class, () -> collection1.query(query));
+
+    query.set(ShardParams.SHARDS_TOLERANT, "true");
+
+    expectThrows(SolrException.class, () -> collection1.query(query));
+  }
+
   public static class BadResponseWriter extends BinaryResponseWriter {
 
     private static boolean failOnGetFields = false;
     private static boolean failOnGetTopIds = false;
+    private static boolean failAllShards = false;
 
     public BadResponseWriter() {
       super();
@@ -240,6 +276,10 @@ public class TestTolerantSearch extends SolrJettyTestBase {
           && req.getParams().getBool("isShard", false) == true) {
         throw new SolrException(
             SolrException.ErrorCode.SERVER_ERROR, "Dummy exception in BadResponseWriter");
+      } else if (failAllShards) {
+        // fail on every shard
+        throw new SolrException(
+            SolrException.ErrorCode.SERVER_ERROR, "Dummy exception in BadResponseWriter");
       }
       super.write(out, req, response);
     }