You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by kr...@apache.org on 2022/09/19 20:27:48 UTC

[solr] branch branch_9x updated: SOLR-16417: NPE if facet query hits timeout or exception (#1025)

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

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


The following commit(s) were added to refs/heads/branch_9x by this push:
     new 7dfaba3738e SOLR-16417: NPE if facet query hits timeout or exception (#1025)
7dfaba3738e is described below

commit 7dfaba3738e3b53f688a19fd3b961966f5ff869e
Author: Kevin Risden <ri...@users.noreply.github.com>
AuthorDate: Mon Sep 19 16:24:47 2022 -0400

    SOLR-16417: NPE if facet query hits timeout or exception (#1025)
---
 solr/CHANGES.txt                                   |   2 +
 .../solr/handler/component/FacetComponent.java     | 100 ++++++++++++---------
 .../apache/solr/response/SolrQueryResponse.java    |   2 +-
 3 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 1e0567d3e2a..57666ee55af 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -129,6 +129,8 @@ Bug Fixes
 
 * SOLR-16344: PlacementPlugin throws NPE for PRS collections (noble)
 
+* SOLR-16417: NPE if facet query hits timeout or exception (Kevin Risden)
+
 Other Changes
 ---------------------
 * SOLR-16351: Upgrade Carrot2 to 4.4.3, upgrade randomizedtesting to 2.8.0. (Dawid Weiss)
diff --git a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
index b27ef43c647..868441f67d5 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java
@@ -34,6 +34,7 @@ import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.FixedBitSet;
+import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.util.ClientUtils;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
@@ -68,6 +69,7 @@ public class FacetComponent extends SearchComponent {
 
   public static final String COMPONENT_NAME = "facet";
 
+  public static final String FACET_COUNTS_KEY = "facet_counts";
   public static final String FACET_QUERY_KEY = "facet_queries";
   public static final String FACET_FIELD_KEY = "facet_fields";
   public static final String FACET_RANGES_KEY = "facet_ranges";
@@ -291,7 +293,7 @@ public class FacetComponent extends SearchComponent {
         fdebug.setElapse(timeElapsed);
       }
 
-      rb.rsp.add("facet_counts", counts);
+      rb.rsp.add(FACET_COUNTS_KEY, counts);
     }
   }
 
@@ -713,38 +715,13 @@ public class FacetComponent extends SearchComponent {
 
     for (ShardResponse srsp : sreq.responses) {
       int shardNum = rb.getShardNum(srsp.getShard());
-      NamedList<?> facet_counts = null;
-      try {
-        facet_counts = (NamedList<?>) srsp.getSolrResponse().getResponse().get("facet_counts");
-        if (facet_counts == null) {
-          NamedList<?> responseHeader =
-              (NamedList<?>) srsp.getSolrResponse().getResponse().get("responseHeader");
-          if (Boolean.TRUE.equals(
-              responseHeader.getBooleanArg(
-                  SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY))) {
-            continue;
-          } else {
-            log.warn(
-                "corrupted response on {} : {}", srsp.getShardRequest(), srsp.getSolrResponse());
-            throw new SolrException(
-                ErrorCode.SERVER_ERROR,
-                "facet_counts is absent in response from "
-                    + srsp.getNodeName()
-                    + ", but "
-                    + SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY
-                    + " hasn't been responded");
-          }
-        }
-      } catch (Exception ex) {
-        if (ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
-          continue; // looks like a shard did not return anything
-        }
-        throw new SolrException(
-            ErrorCode.SERVER_ERROR, "Unable to read facet info for shard: " + srsp.getShard(), ex);
+      NamedList<?> facet_counts = getFacetCountsFromShardResponse(rb, srsp);
+      if (facet_counts == null) {
+        continue; // looks like a shard did not return anything
       }
 
       // handle facet queries
-      NamedList<?> facet_queries = (NamedList<?>) facet_counts.get("facet_queries");
+      NamedList<?> facet_queries = (NamedList<?>) facet_counts.get(FACET_QUERY_KEY);
       if (facet_queries != null) {
         for (int i = 0; i < facet_queries.size(); i++) {
           String returnedKey = facet_queries.getName(i);
@@ -755,7 +732,7 @@ public class FacetComponent extends SearchComponent {
       }
 
       // step through each facet.field, adding results from this shard
-      NamedList<?> facet_fields = (NamedList<?>) facet_counts.get("facet_fields");
+      NamedList<?> facet_fields = (NamedList<?>) facet_counts.get(FACET_FIELD_KEY);
 
       if (facet_fields != null) {
         for (DistribFieldFacet dff : fi.facets.values()) {
@@ -766,7 +743,7 @@ public class FacetComponent extends SearchComponent {
       // Distributed facet_ranges
       @SuppressWarnings("unchecked")
       SimpleOrderedMap<SimpleOrderedMap<Object>> rangesFromShard =
-          (SimpleOrderedMap<SimpleOrderedMap<Object>>) facet_counts.get("facet_ranges");
+          (SimpleOrderedMap<SimpleOrderedMap<Object>>) facet_counts.get(FACET_RANGES_KEY);
       if (rangesFromShard != null) {
         RangeFacetRequest.DistribRangeFacet.mergeFacetRangesFromShardResponse(
             fi.rangeFacets, rangesFromShard);
@@ -862,6 +839,42 @@ public class FacetComponent extends SearchComponent {
     removeQueryFacetsUnderLimits(rb);
   }
 
+  private static NamedList<?> getFacetCountsFromShardResponse(
+      ResponseBuilder rb, ShardResponse srsp) {
+    NamedList<?> facet_counts;
+    try {
+      SolrResponse solrResponse = srsp.getSolrResponse();
+      NamedList<Object> response = solrResponse.getResponse();
+      facet_counts = (NamedList<?>) response.get(FACET_COUNTS_KEY);
+      if (facet_counts != null) {
+        return facet_counts;
+      } else {
+        NamedList<?> responseHeader =
+            (NamedList<?>) response.get(SolrQueryResponse.RESPONSE_HEADER_KEY);
+        if (responseHeader.getBooleanArg(SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY)) {
+          return null;
+        } else {
+          log.warn("corrupted response on {} : {}", srsp.getShardRequest(), solrResponse);
+          throw new SolrException(
+              ErrorCode.SERVER_ERROR,
+              FACET_COUNTS_KEY
+                  + " is absent in response from "
+                  + srsp.getNodeName()
+                  + ", but "
+                  + SolrQueryResponse.RESPONSE_HEADER_PARTIAL_RESULTS_KEY
+                  + " isn't set in the response.");
+        }
+      }
+    } catch (Exception ex) {
+      if (ShardParams.getShardsTolerantAsBool(rb.req.getParams())) {
+        return null;
+      } else {
+        throw new SolrException(
+            ErrorCode.SERVER_ERROR, "Unable to read facet info for shard: " + srsp.getShard(), ex);
+      }
+    }
+  }
+
   private void removeQueryFacetsUnderLimits(ResponseBuilder rb) {
     if (rb.stage != ResponseBuilder.STAGE_EXECUTE_QUERY) {
       return;
@@ -936,7 +949,7 @@ public class FacetComponent extends SearchComponent {
   private void doDistribIntervals(FacetInfo fi, NamedList<?> facet_counts) {
     @SuppressWarnings("unchecked")
     SimpleOrderedMap<SimpleOrderedMap<Integer>> facet_intervals =
-        (SimpleOrderedMap<SimpleOrderedMap<Integer>>) facet_counts.get("facet_intervals");
+        (SimpleOrderedMap<SimpleOrderedMap<Integer>>) facet_counts.get(FACET_INTERVALS_KEY);
 
     if (facet_intervals != null) {
 
@@ -998,10 +1011,11 @@ public class FacetComponent extends SearchComponent {
     FacetInfo fi = rb._facetInfo;
 
     for (ShardResponse srsp : sreq.responses) {
-      // int shardNum = rb.getShardNum(srsp.shard);
-      NamedList<?> facet_counts =
-          (NamedList<?>) srsp.getSolrResponse().getResponse().get("facet_counts");
-      NamedList<?> facet_fields = (NamedList<?>) facet_counts.get("facet_fields");
+      NamedList<?> facet_counts = getFacetCountsFromShardResponse(rb, srsp);
+      if (facet_counts == null) {
+        continue; // looks like a shard did not return anything
+      }
+      NamedList<?> facet_fields = (NamedList<?>) facet_counts.get(FACET_FIELD_KEY);
 
       if (facet_fields == null) continue; // this can happen when there's an exception
 
@@ -1041,7 +1055,7 @@ public class FacetComponent extends SearchComponent {
       int shardNumber = rb.getShardNum(srsp.getShard());
 
       NamedList<?> facetCounts =
-          (NamedList<?>) srsp.getSolrResponse().getResponse().get("facet_counts");
+          (NamedList<?>) srsp.getSolrResponse().getResponse().get(FACET_COUNTS_KEY);
 
       @SuppressWarnings("unchecked")
       NamedList<List<NamedList<Object>>> pivotFacetResponsesFromShard =
@@ -1109,13 +1123,13 @@ public class FacetComponent extends SearchComponent {
     NamedList<Object> facet_counts = new SimpleOrderedMap<>();
 
     NamedList<Number> facet_queries = new SimpleOrderedMap<>();
-    facet_counts.add("facet_queries", facet_queries);
+    facet_counts.add(FACET_QUERY_KEY, facet_queries);
     for (QueryFacet qf : fi.queryFacets.values()) {
       facet_queries.add(qf.getKey(), num(qf.count));
     }
 
     NamedList<Object> facet_fields = new SimpleOrderedMap<>();
-    facet_counts.add("facet_fields", facet_fields);
+    facet_counts.add(FACET_FIELD_KEY, facet_fields);
 
     for (DistribFieldFacet dff : fi.facets.values()) {
       // order is important for facet values, so use NamedList
@@ -1174,9 +1188,9 @@ public class FacetComponent extends SearchComponent {
       RangeFacetRequest.DistribRangeFacet value = entry.getValue();
       rangeFacetOutput.add(key, value.rangeFacet);
     }
-    facet_counts.add("facet_ranges", rangeFacetOutput);
+    facet_counts.add(FACET_RANGES_KEY, rangeFacetOutput);
 
-    facet_counts.add("facet_intervals", fi.intervalFacets);
+    facet_counts.add(FACET_INTERVALS_KEY, fi.intervalFacets);
     facet_counts.add(
         SpatialHeatmapFacets.RESPONSE_KEY,
         SpatialHeatmapFacets.distribFinish(fi.heatmapFacets, rb));
@@ -1185,7 +1199,7 @@ public class FacetComponent extends SearchComponent {
       facet_counts.add(PIVOT_KEY, createPivotFacetOutput(rb));
     }
 
-    rb.rsp.add("facet_counts", facet_counts);
+    rb.rsp.add(FACET_COUNTS_KEY, facet_counts);
 
     rb._facetInfo = null; // could be big, so release asap
   }
diff --git a/solr/core/src/java/org/apache/solr/response/SolrQueryResponse.java b/solr/core/src/java/org/apache/solr/response/SolrQueryResponse.java
index bdca96f3789..55b62eaff37 100644
--- a/solr/core/src/java/org/apache/solr/response/SolrQueryResponse.java
+++ b/solr/core/src/java/org/apache/solr/response/SolrQueryResponse.java
@@ -63,7 +63,7 @@ public class SolrQueryResponse {
   public static final String RESPONSE_HEADER_PARTIAL_RESULTS_KEY = "partialResults";
   public static final String RESPONSE_HEADER_SEGMENT_TERMINATED_EARLY_KEY =
       "segmentTerminatedEarly";
-  private static final String RESPONSE_HEADER_KEY = "responseHeader";
+  public static final String RESPONSE_HEADER_KEY = "responseHeader";
   private static final String RESPONSE_KEY = "response";
 
   /**