diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index ca1d95898f4..3923ecc4892 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -154,6 +154,8 @@ Other Changes * SOLR-16332: Upgrade Jetty to 9.4.48.v20220622 (Chris Sabelstrom, janhoy) +* SOLR-16339: Refined "no servers hosting shard" SolrException wording. (Christine Poerschke) + Build --------------------- * SOLR-16204: Change Lucene dependency to Lucene 9.1.0 (Elia Porciani via Alessandro Benedetti) 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 a1aabf3c850..dd1d7ac04b2 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 @@ -31,6 +31,7 @@ import org.apache.solr.client.solrj.impl.LBHttp2SolrClient; import org.apache.solr.client.solrj.impl.LBSolrClient; import org.apache.solr.client.solrj.request.QueryRequest; +import org.apache.solr.client.solrj.routing.NoOpReplicaListTransformer; import org.apache.solr.client.solrj.routing.ReplicaListTransformer; import org.apache.solr.client.solrj.util.AsyncListener; import org.apache.solr.client.solrj.util.Cancellable; @@ -148,7 +149,7 @@ public void submit( pending.incrementAndGet(); // if there are no shards available for a slice, urls.size()==0 - if (urls.size() == 0) { + if (urls.isEmpty()) { // TODO: what's the right error code here? We should use the same thing when // all of the servers for a shard are down. SolrException exception = @@ -318,14 +319,26 @@ public void prepDistributed(ResponseBuilder rb) { // be an optimization? } - for (int i = 0; i < rb.slices.length; i++) { - if (!ShardParams.getShardsTolerantAsBool(params) - && replicaSource.getReplicasBySlice(i).isEmpty()) { - // stop the check when there are no replicas available for a shard - // todo fix use of slices[i] which can be null if user specified urls in shards param - throw new SolrException( - SolrException.ErrorCode.SERVICE_UNAVAILABLE, - "no servers hosting shard: " + rb.slices[i]); + if (!ShardParams.getShardsTolerantAsBool(params)) { + for (int i = 0; i < rb.slices.length; i++) { + if (replicaSource.getReplicasBySlice(i).isEmpty()) { + final ReplicaSource allActiveReplicaSource = + new CloudReplicaSource.Builder() + .params(params) + .zkStateReader(zkController.getZkStateReader()) + .allowListUrlChecker(AllowListUrlChecker.ALLOW_ALL) + .replicaListTransformer(NoOpReplicaListTransformer.INSTANCE) + .collection(cloudDescriptor.getCollectionName()) + .onlyNrt(false) + .build(); + final String adjective = + (allActiveReplicaSource.getReplicasBySlice(i).isEmpty() ? "active" : "eligible"); + // stop the check when there are no replicas available for a shard + // todo fix use of slices[i] which can be null if user specified urls in shards param + throw new SolrException( + SolrException.ErrorCode.SERVICE_UNAVAILABLE, + "no " + adjective + " servers hosting shard: " + rb.slices[i]); + } } } } else { diff --git a/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java index f2135d876e8..cbe361a3bf3 100644 --- a/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java +++ b/solr/core/src/test/org/apache/solr/handler/component/SearchHandlerTest.java @@ -263,7 +263,7 @@ public void testRequireZkConnectedDistrib() throws Exception { try (HttpSolrClient httpSolrClient = new HttpSolrClient.Builder(connectedReplica.getCoreUrl()).build()) { ignoreException("ZooKeeper is not connected"); - ignoreException("no servers hosting shard:"); + ignoreException("no active servers hosting shard:"); JettySolrRunner disconnectedJetty = miniCluster.getReplicaJetty(disconnectedReplica); disconnectedJetty.getCoreContainer().getZkController().getZkClient().close(); req.process(httpSolrClient); @@ -272,12 +272,12 @@ public void testRequireZkConnectedDistrib() throws Exception { } catch (Exception e) { assertTrue( "Unrecognized exception message: " + e, - e.getMessage().contains("no servers hosting shard:") + e.getMessage().contains("no active servers hosting shard:") || e.getMessage().contains("ZooKeeper is not connected")); } } finally { miniCluster.shutdown(); - unIgnoreException("no servers hosting shard:"); + unIgnoreException("no active servers hosting shard:"); unIgnoreException("ZooKeeper is not connected"); } } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NoOpReplicaListTransformer.java b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NoOpReplicaListTransformer.java new file mode 100644 index 00000000000..8b968e12a5f --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NoOpReplicaListTransformer.java @@ -0,0 +1,28 @@ +/* + * 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.client.solrj.routing; + +import java.util.List; + +public final class NoOpReplicaListTransformer implements ReplicaListTransformer { + + public static final ReplicaListTransformer INSTANCE = new NoOpReplicaListTransformer(); + + private NoOpReplicaListTransformer() {} + + public void transform(List choices) {} +} diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NodePreferenceRulesComparator.java b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NodePreferenceRulesComparator.java index 11560817b70..0ceb5141eec 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NodePreferenceRulesComparator.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/routing/NodePreferenceRulesComparator.java @@ -100,13 +100,7 @@ public NodePreferenceRulesComparator( } } - private static final ReplicaListTransformer NOOP_RLT = - new ReplicaListTransformer() { - @Override - public void transform(List choices) { - // Cannot use a method reference because of generic types! - } - }; + private static final ReplicaListTransformer NOOP_RLT = NoOpReplicaListTransformer.INSTANCE; private static final ReplicaListTransformerFactory NOOP_RLTF = (String configSpec, SolrParams requestParams, ReplicaListTransformerFactory fallback) -> NOOP_RLT; diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/routing/ReplicaListTransformerTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/routing/ReplicaListTransformerTest.java index 82d05287bb8..61e4150e28e 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/routing/ReplicaListTransformerTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/routing/ReplicaListTransformerTest.java @@ -68,17 +68,6 @@ public void transform(List choices) { } } - // A transformer that makes no transformation - private static class ToyNoOpReplicaListTransformer implements ReplicaListTransformer { - - public ToyNoOpReplicaListTransformer() {} - - public void transform(List choices) { - // no-op - log.info("No-Op transform ignoring input: {}", choices); - } - } - @Test public void testTransform() throws Exception { @@ -99,7 +88,7 @@ protected ReplicaListTransformer getReplicaListTransformer(final SolrQueryReques final SolrParams params = req.getParams(); if (params.getBool("toyNoTransform", false)) { - return new ToyNoOpReplicaListTransformer(); + return NoOpReplicaListTransformer.INSTANCE; } final String regex = params.get("toyRegEx");