diff --git a/changelog/unreleased/SOLR-17712-Deprecate CommonAdminParams.waitForFinalState and make true default.yml b/changelog/unreleased/SOLR-17712-Deprecate CommonAdminParams.waitForFinalState and make true default.yml new file mode 100644 index 00000000000..b25af7adc15 --- /dev/null +++ b/changelog/unreleased/SOLR-17712-Deprecate CommonAdminParams.waitForFinalState and make true default.yml @@ -0,0 +1,9 @@ +title: SolrCloud admin commands should more reliably be fully completed when Solr returns a response. + The `waitForFinalState` param now defaults to true and is deprecated. (Abhishek Umarjikar) +type: changed +authors: +- name: Abhishek Umarjikar +- name: David Smiley +links: +- name: SOLR-17712 + url: https://issues.apache.org/jira/browse/SOLR-17712 diff --git a/solr/api/src/java/org/apache/solr/client/api/model/BalanceReplicasRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/BalanceReplicasRequestBody.java index 508e5288cd4..77b7b860db8 100644 --- a/solr/api/src/java/org/apache/solr/client/api/model/BalanceReplicasRequestBody.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/BalanceReplicasRequestBody.java @@ -24,9 +24,8 @@ public class BalanceReplicasRequestBody { public BalanceReplicasRequestBody() {} - public BalanceReplicasRequestBody(Set nodes, Boolean waitForFinalState, String async) { + public BalanceReplicasRequestBody(Set nodes, String async) { this.nodes = nodes; - this.waitForFinalState = waitForFinalState; this.async = async; } diff --git a/solr/core/src/java/org/apache/solr/cloud/ActiveReplicaWatcher.java b/solr/core/src/java/org/apache/solr/cloud/ActiveReplicaWatcher.java index 30cd1ba165d..3e85ca9081b 100644 --- a/solr/core/src/java/org/apache/solr/cloud/ActiveReplicaWatcher.java +++ b/solr/core/src/java/org/apache/solr/cloud/ActiveReplicaWatcher.java @@ -19,10 +19,12 @@ import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Set; import org.apache.solr.common.SolrCloseableLatch; import org.apache.solr.common.cloud.CollectionStateWatcher; import org.apache.solr.common.cloud.DocCollection; +import org.apache.solr.common.cloud.PerReplicaStates; import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.Slice; import org.apache.solr.common.cloud.ZkStateReader; @@ -45,6 +47,7 @@ public class ActiveReplicaWatcher implements CollectionStateWatcher { private final List activeReplicas = new ArrayList<>(); private int lastZkVersion = -1; + private PerReplicaStates lastPrs; private SolrCloseableLatch latch; @@ -150,11 +153,13 @@ public synchronized boolean onStateChanged(Set liveNodes, DocCollection log.debug("-- already done, exiting..."); return true; } - if (collectionState.getZNodeVersion() == lastZkVersion) { + if (collectionState.getZNodeVersion() == lastZkVersion + && Objects.equals(lastPrs, collectionState.getPerReplicaStates())) { log.debug("-- spurious call with already seen zkVersion= {}, ignoring...", lastZkVersion); return false; } lastZkVersion = collectionState.getZNodeVersion(); + lastPrs = collectionState.getPerReplicaStates(); for (Slice slice : collectionState.getSlices()) { for (Replica replica : slice.getReplicas()) { diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java index a71a515c56d..9b651d88922 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/AddReplicaCmd.java @@ -114,7 +114,7 @@ List addReplica( "Collection: " + collectionName + " shard: " + shard + " does not exist"); } - boolean waitForFinalState = message.getBool(WAIT_FOR_FINAL_STATE, false); + boolean waitForFinalState = message.getBool(WAIT_FOR_FINAL_STATE, true); boolean skipCreateReplicaInClusterState = message.getBool(SKIP_CREATE_REPLICA_IN_CLUSTER_STATE, false); final String asyncId = message.getStr(ASYNC); @@ -177,21 +177,29 @@ List addReplica( shardRequestTracker.sendShardRequest(createReplica.node, params, shardHandler); } + SolrCloseableLatch waitForFinalStateLatch = + new SolrCloseableLatch(totalReplicas, ccc.getCloseableToLatchOn()); + Runnable runnable = () -> { shardRequestTracker.processResponses( results, shardHandler, true, "ADDREPLICA failed to create replica"); - for (CreateReplica replica : createReplicas) { - CollectionHandlingUtils.waitForCoreNodeName( - collectionName, replica.node, replica.coreName, ccc.getZkStateReader()); + // if there were errors, don't do any more waiting + if (results.get("failure") != null) { + while (waitForFinalStateLatch.getCount() > 0) { + waitForFinalStateLatch.countDown(); + } + } else { + for (CreateReplica replica : createReplicas) { + CollectionHandlingUtils.waitForCoreNodeName( + collectionName, replica.node, replica.coreName, ccc.getZkStateReader()); + } } if (onComplete != null) onComplete.run(); }; if (!parallel || waitForFinalState) { if (waitForFinalState) { - SolrCloseableLatch latch = - new SolrCloseableLatch(totalReplicas, ccc.getCloseableToLatchOn()); ActiveReplicaWatcher watcher = new ActiveReplicaWatcher( collectionName, @@ -199,11 +207,11 @@ List addReplica( createReplicas.stream() .map(createReplica -> createReplica.coreName) .collect(Collectors.toList()), - latch); + waitForFinalStateLatch); try { zkStateReader.registerCollectionStateWatcher(collectionName, watcher); runnable.run(); - if (!latch.await(timeout, TimeUnit.SECONDS)) { + if (!waitForFinalStateLatch.await(timeout, TimeUnit.SECONDS)) { throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "Timeout waiting " + timeout + " seconds for replica to become active."); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/BalanceReplicasCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/BalanceReplicasCmd.java index 7d84c7c6633..7e6ee573dd2 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/BalanceReplicasCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/BalanceReplicasCmd.java @@ -59,7 +59,7 @@ public void call(ClusterState state, ZkNodeProps message, NamedList resu "'nodes' was not passed as a correct type (Set/List/String): " + nodesRaw.getClass().getName()); } - boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, false); + boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, true); String async = message.getStr(ASYNC); int timeout = message.getInt("timeout", 10 * 60); // 10 minutes boolean parallel = message.getBool("parallel", false); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CollectionHandlingUtils.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CollectionHandlingUtils.java index 806ad86ba04..f35c5ad97c0 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CollectionHandlingUtils.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CollectionHandlingUtils.java @@ -666,6 +666,18 @@ public void sendShardRequest( shardHandler.submit(sreq, replica, sreq.params); } + /** + * Processes all responses (waiting, if necessary), populating "success" or "failure" keyed data + * into {@code results} per shard response in turn keyed by node. If {@code asyncId} mode, will + * wait for their completion. + * + * @param results will hold shard request results aggregated to "success" and "failure" keys. + * @param abortOnError if any shard request has an exception, throw it. This doesn't apply to + * "STATUS=failed" responses. + * @param msgOnError the exception message for {@code abortOnError} + */ + // TODO it's too confusing how we sometime abort on error yet if async or find STATUS=FAILED not + // Recommend not doing any abort. Have a separate utility method that looks for "failure". void processResponses( NamedList results, ShardHandler shardHandler, @@ -698,8 +710,8 @@ void processResponses( } while (srsp != null); // If request is async wait for the core admin to complete before returning + // note: ignore abortOnError when async if (asyncId != null) { - // TODO: Shouldn't we abort with msgOnError exception when failure? waitForAsyncCallsToComplete(results); shardAsyncIdByNode.clear(); } diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java index 80cc02664bd..5cfd743a149 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/CreateCollectionCmd.java @@ -108,7 +108,7 @@ public void call(ClusterState clusterState, ZkNodeProps message, NamedList resu ZkStateReader zkStateReader = ccc.getZkStateReader(); Set sourceNodes = getNodesFromParam(message, CollectionParams.SOURCE_NODES); Set targetNodes = getNodesFromParam(message, CollectionParams.TARGET_NODES); - boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, false); + boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, true); if (sourceNodes.isEmpty()) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "sourceNodes is a required param"); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java index 48f065f537e..319d90a70fb 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/MoveReplicaCmd.java @@ -73,7 +73,7 @@ private void moveReplica( CollectionHandlingUtils.checkRequired(message, COLLECTION_PROP, CollectionParams.TARGET_NODE); String extCollection = message.getStr(COLLECTION_PROP); String targetNode = message.getStr(CollectionParams.TARGET_NODE); - boolean waitForFinalState = message.getBool(WAIT_FOR_FINAL_STATE, false); + boolean waitForFinalState = message.getBool(WAIT_FOR_FINAL_STATE, true); boolean inPlaceMove = message.getBool(IN_PLACE_MOVE, true); int timeout = message.getInt(TIMEOUT, 10 * 60); // 10 minutes diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java index 5134e9953bd..93bf263ac85 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/ReplaceNodeCmd.java @@ -50,7 +50,7 @@ public void call(ClusterState state, ZkNodeProps message, NamedList resu ZkStateReader zkStateReader = ccc.getZkStateReader(); String source = message.getStr(CollectionParams.SOURCE_NODE); String target = message.getStr(CollectionParams.TARGET_NODE); - boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, false); + boolean waitForFinalState = message.getBool(CommonAdminParams.WAIT_FOR_FINAL_STATE, true); if (source == null) { throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "sourceNode is a required param"); diff --git a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java index 8548a0bc17a..c0ebc7d3b1f 100644 --- a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java +++ b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java @@ -136,7 +136,7 @@ public boolean split(ClusterState clusterState, ZkNodeProps message, NamedList execute( final RequiredSolrParams requiredParams = req.getParams().required(); final var requestBody = new ReplaceNodeRequestBody(); requestBody.targetNodeName = params.get(TARGET_NODE); - requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); requestBody.async = params.get(ASYNC); final ReplaceNode replaceNodeAPI = new ReplaceNode(h.coreContainer, req, rsp); final SolrJerseyResponse replaceNodeResponse = diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/BalanceReplicas.java b/solr/core/src/java/org/apache/solr/handler/admin/api/BalanceReplicas.java index b582e39464b..263c64212a9 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/BalanceReplicas.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/BalanceReplicas.java @@ -19,7 +19,6 @@ import static org.apache.solr.cloud.Overseer.QUEUE_OPERATION; import static org.apache.solr.common.params.CollectionParams.NODES; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; @@ -75,7 +74,6 @@ public ZkNodeProps createRemoteMessage(BalanceReplicasRequestBody requestBody) { final Map remoteMessage = new HashMap<>(); if (requestBody != null) { insertIfNotNull(remoteMessage, NODES, requestBody.nodes); - insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfNotNull(remoteMessage, ASYNC, requestBody.async); } remoteMessage.put(QUEUE_OPERATION, CollectionAction.BALANCE_REPLICAS.toLower()); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollection.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollection.java index fef25cfdb52..19584a21828 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollection.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollection.java @@ -34,7 +34,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.REPLICATION_FACTOR; import static org.apache.solr.common.params.CollectionAdminParams.TLOG_REPLICAS; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CoreAdminParams.NAME; import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT; import static org.apache.solr.handler.admin.CollectionsHandler.waitForActiveCollection; @@ -173,7 +172,6 @@ public static ZkNodeProps createRemoteMessage(CreateCollectionRequestBody reqBod rawProperties.put(SHARDS_PROP, String.join(",", reqBody.shardNames)); rawProperties.put(PULL_REPLICAS, reqBody.pullReplicas); rawProperties.put(TLOG_REPLICAS, reqBody.tlogReplicas); - rawProperties.put(WAIT_FOR_FINAL_STATE, reqBody.waitForFinalState); rawProperties.put(PER_REPLICA_STATE, reqBody.perReplicaState); rawProperties.put(ALIAS, reqBody.alias); rawProperties.put(ASYNC, reqBody.async); @@ -266,7 +264,6 @@ public static CreateCollectionRequestBody createRequestBodyFromV1Params( requestBody.tlogReplicas = params.getInt(ZkStateReader.TLOG_REPLICAS); requestBody.pullReplicas = params.getInt(ZkStateReader.PULL_REPLICAS); requestBody.nrtReplicas = params.getInt(ZkStateReader.NRT_REPLICAS); - requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); requestBody.perReplicaState = params.getBool(PER_REPLICA_STATE); requestBody.alias = params.get(ALIAS); requestBody.async = params.get(ASYNC); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java index 72c8eb058b1..91b99c0f737 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java @@ -30,7 +30,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_PREFIX; import static org.apache.solr.common.params.CollectionAdminParams.SKIP_NODE_ASSIGNMENT; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CoreAdminParams.DATA_DIR; import static org.apache.solr.common.params.CoreAdminParams.INSTANCE_DIR; import static org.apache.solr.common.params.CoreAdminParams.NAME; @@ -114,7 +113,6 @@ public static ZkNodeProps createRemoteMessage( insertIfNotNull(remoteMessage, DATA_DIR, requestBody.dataDir); insertIfNotNull(remoteMessage, ULOG_DIR, requestBody.ulogDir); insertIfNotNull(remoteMessage, REPLICA_TYPE, requestBody.type); - insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfNotNull(remoteMessage, NRT_REPLICAS, requestBody.nrtReplicas); insertIfNotNull(remoteMessage, TLOG_REPLICAS, requestBody.tlogReplicas); insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas); @@ -146,7 +144,6 @@ public static CreateReplicaRequestBody createRequestBodyFromV1Params(SolrParams requestBody.nrtReplicas = params.getInt(NRT_REPLICAS); requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS); requestBody.pullReplicas = params.getInt(PULL_REPLICAS); - requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); requestBody.followAliases = params.getBool(FOLLOW_ALIASES); requestBody.async = params.get(ASYNC); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java index 2912fbd8e07..66d581a894f 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java @@ -31,7 +31,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.PROPERTY_PREFIX; import static org.apache.solr.common.params.CollectionAdminParams.SHARD; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CommonParams.NAME; import static org.apache.solr.handler.admin.api.CreateCollection.copyPrefixedPropertiesWithoutPrefix; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; @@ -113,7 +112,6 @@ public static CreateShardRequestBody createRequestBodyFromV1Params(SolrParams pa requestBody.nodeSet = Arrays.asList(nodeSetStr.split(",")); } } - requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE); requestBody.followAliases = params.getBool(FOLLOW_ALIASES); requestBody.async = params.get(ASYNC); requestBody.properties = @@ -152,7 +150,6 @@ public static ZkNodeProps createRemoteMessage( insertIfNotNull(remoteMessage, NRT_REPLICAS, requestBody.nrtReplicas); insertIfNotNull(remoteMessage, TLOG_REPLICAS, requestBody.tlogReplicas); insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas); - insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfNotNull(remoteMessage, FOLLOW_ALIASES, requestBody.followAliases); insertIfNotNull(remoteMessage, ASYNC, requestBody.async); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java b/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java index 670540b4f74..d5bc6dbc983 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/MigrateReplicas.java @@ -20,7 +20,6 @@ import static org.apache.solr.common.params.CollectionParams.SOURCE_NODES; import static org.apache.solr.common.params.CollectionParams.TARGET_NODES; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; @@ -83,7 +82,6 @@ public ZkNodeProps createRemoteMessage(MigrateReplicasRequestBody requestBody) { } insertIfNotNull(remoteMessage, SOURCE_NODES, requestBody.sourceNodes); insertIfNotNull(remoteMessage, TARGET_NODES, requestBody.targetNodes); - insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfNotNull(remoteMessage, ASYNC, requestBody.async); } else { throw new SolrException( diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ReplaceNode.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ReplaceNode.java index bb36f2036df..d9b035d0655 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/ReplaceNode.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ReplaceNode.java @@ -20,7 +20,6 @@ import static org.apache.solr.common.params.CollectionParams.SOURCE_NODE; import static org.apache.solr.common.params.CollectionParams.TARGET_NODE; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT; import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM; @@ -82,7 +81,6 @@ public ZkNodeProps createRemoteMessage(String nodeName, ReplaceNodeRequestBody r remoteMessage.put(SOURCE_NODE, nodeName); if (requestBody != null) { insertIfValueNotNull(remoteMessage, TARGET_NODE, requestBody.targetNodeName); - insertIfValueNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState); insertIfValueNotNull(remoteMessage, ASYNC, requestBody.async); } remoteMessage.put(QUEUE_OPERATION, CollectionAction.REPLACENODE.toLower()); diff --git a/solr/core/src/test/org/apache/solr/cloud/BalanceReplicasTest.java b/solr/core/src/test/org/apache/solr/cloud/BalanceReplicasTest.java index b1144d5caff..0c3a9a85f9d 100644 --- a/solr/core/src/test/org/apache/solr/cloud/BalanceReplicasTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/BalanceReplicasTest.java @@ -149,7 +149,7 @@ public void testSomeNodes() throws Exception { cluster.getSolrClient(), "/api/cluster/replicas/balance", Utils.getReflectWriter( - new BalanceReplicasRequestBody(new HashSet<>(l.subList(1, 4)), true, null))); + new BalanceReplicasRequestBody(new HashSet<>(l.subList(1, 4)), null))); collection = cloudClient.getClusterState().getCollectionOrNull(coll, false); log.debug("### After balancing: {}", collection); diff --git a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java index 80a8377e791..e298c252128 100644 --- a/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/MigrateReplicasTest.java @@ -126,7 +126,7 @@ public void test() throws Exception { callMigrateReplicas( cloudClient, new MigrateReplicasRequestBody( - Set.of(nodeToBeDecommissioned), Set.of(emptyNode), true, null)); + Set.of(nodeToBeDecommissioned), Set.of(emptyNode), null)); assertEquals( "MigrateReplicas request was unsuccessful", 0L, @@ -154,7 +154,7 @@ public void test() throws Exception { callMigrateReplicas( cloudClient, new MigrateReplicasRequestBody( - Set.of(emptyNode), Set.of(nodeToBeDecommissioned), true, null)); + Set.of(emptyNode), Set.of(nodeToBeDecommissioned), null)); assertEquals( "MigrateReplicas request was unsuccessful", 0L, @@ -269,7 +269,7 @@ public void testWithNoTarget() throws Exception { callMigrateReplicas( cloudClient, new MigrateReplicasRequestBody( - new HashSet<>(nodesToBeDecommissioned), Collections.emptySet(), true, null)); + new HashSet<>(nodesToBeDecommissioned), Collections.emptySet(), null)); assertEquals( "MigrateReplicas request was unsuccessful", 0L, @@ -318,7 +318,7 @@ public void testFailOnSingleNode() throws Exception { Map response = callMigrateReplicas( cloudClient, - new MigrateReplicasRequestBody(Set.of(liveNode), Collections.emptySet(), true, null)); + new MigrateReplicasRequestBody(Set.of(liveNode), Collections.emptySet(), null)); assertNotNull( "No error in response, when the request should have failed", response.get("error")); assertEquals( diff --git a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java index d7cf33aad8a..7c587e6834d 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestPullReplica.java @@ -769,11 +769,11 @@ public void testSkipLeaderRecoveryProperty() throws Exception { numDocsAdded, getCollectionState(collectionName).getReplicas(EnumSet.of(Replica.Type.PULL))); - // Add yetanother PULL replica while the leader is down. - // This new replica will immediately stall going into recoveery, since the leader is down. + // Add yet another PULL replica while the leader is down. + // This new replica will immediately stall going into recovery, since the leader is down. CollectionAdminRequest.addReplicaToShard(collectionName, "shard1", Replica.Type.PULL) .setCreateNodeSet(pullFollowerJetty.getNodeName()) - .process(cluster.getSolrClient()); + .processAsync(cluster.getSolrClient()); waitForState( "3rd PULL replica should be down", collectionName, diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateCollectionAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateCollectionAPITest.java index 80a2200131a..c7f91ed7425 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateCollectionAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateCollectionAPITest.java @@ -31,7 +31,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.REPLICATION_FACTOR; import static org.apache.solr.common.params.CollectionAdminParams.TLOG_REPLICAS; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CoreAdminParams.NAME; import java.util.List; @@ -134,7 +133,6 @@ public void testCreateRemoteMessageAllProperties() { requestBody.shardNames = List.of("shard1", "shard2"); requestBody.pullReplicas = 789; requestBody.tlogReplicas = 987; - requestBody.waitForFinalState = false; requestBody.perReplicaState = true; requestBody.alias = "someAliasName"; requestBody.properties = Map.of("propName", "propValue"); @@ -157,7 +155,6 @@ public void testCreateRemoteMessageAllProperties() { assertEquals(789, remoteMessage.get(PULL_REPLICAS)); assertEquals(987, remoteMessage.get(TLOG_REPLICAS)); assertEquals(123, remoteMessage.get(NRT_REPLICAS)); // replicationFactor value used - assertEquals(false, remoteMessage.get(WAIT_FOR_FINAL_STATE)); assertEquals(true, remoteMessage.get(PER_REPLICA_STATE)); assertEquals("someAliasName", remoteMessage.get(ALIAS)); assertEquals("propValue", remoteMessage.get("property.propName")); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java index 2abe5d13397..03dc620654b 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java @@ -28,7 +28,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.FOLLOW_ALIASES; import static org.apache.solr.common.params.CollectionAdminParams.SKIP_NODE_ASSIGNMENT; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.apache.solr.common.params.CoreAdminParams.DATA_DIR; import static org.apache.solr.common.params.CoreAdminParams.INSTANCE_DIR; import static org.apache.solr.common.params.CoreAdminParams.NAME; @@ -105,7 +104,6 @@ public void testCreateRemoteMessageAllProperties() { requestBody.nodeSet = List.of("node1", "node2"); requestBody.node = "node3"; requestBody.skipNodeAssignment = Boolean.TRUE; - requestBody.waitForFinalState = true; requestBody.followAliases = true; requestBody.async = "someAsyncId"; requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2"); @@ -114,7 +112,7 @@ public void testCreateRemoteMessageAllProperties() { CreateReplica.createRemoteMessage("someCollectionName", "someShardName", requestBody) .getProperties(); - assertEquals(20, remoteMessage.size()); + assertEquals(19, remoteMessage.size()); assertEquals("addreplica", remoteMessage.get(QUEUE_OPERATION)); assertEquals("someCollectionName", remoteMessage.get(COLLECTION)); assertEquals("someShardName", remoteMessage.get(SHARD_ID_PROP)); @@ -130,7 +128,6 @@ public void testCreateRemoteMessageAllProperties() { assertEquals("node1,node2", remoteMessage.get(CREATE_NODE_SET_PARAM)); assertEquals("node3", remoteMessage.get(NODE)); assertEquals(Boolean.TRUE, remoteMessage.get(SKIP_NODE_ASSIGNMENT)); - assertEquals(true, remoteMessage.get(WAIT_FOR_FINAL_STATE)); assertEquals(true, remoteMessage.get(FOLLOW_ALIASES)); assertEquals("someAsyncId", remoteMessage.get(ASYNC)); assertEquals("propVal1", remoteMessage.get("property.propName1")); @@ -154,7 +151,6 @@ public void testCanConvertV1ParamsToV2RequestBody() { v1Params.add(CREATE_NODE_SET_PARAM, "node1,node2"); v1Params.add(NODE, "node3"); v1Params.set(SKIP_NODE_ASSIGNMENT, true); - v1Params.set(WAIT_FOR_FINAL_STATE, true); v1Params.set(FOLLOW_ALIASES, true); v1Params.add(ASYNC, "someAsyncId"); v1Params.add("property.propName1", "propVal1"); @@ -174,7 +170,6 @@ public void testCanConvertV1ParamsToV2RequestBody() { assertEquals(List.of("node1", "node2"), requestBody.nodeSet); assertEquals("node3", requestBody.node); assertEquals(Boolean.TRUE, requestBody.skipNodeAssignment); - assertEquals(Boolean.TRUE, requestBody.waitForFinalState); assertEquals(Boolean.TRUE, requestBody.followAliases); assertEquals("someAsyncId", requestBody.async); assertEquals("propVal1", requestBody.properties.get("propName1")); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java index a8bc3edf658..58e9cac866f 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java @@ -27,7 +27,6 @@ import static org.apache.solr.common.params.CollectionAdminParams.CREATE_NODE_SET_PARAM; import static org.apache.solr.common.params.CollectionAdminParams.FOLLOW_ALIASES; import static org.apache.solr.common.params.CommonAdminParams.ASYNC; -import static org.apache.solr.common.params.CommonAdminParams.WAIT_FOR_FINAL_STATE; import static org.hamcrest.Matchers.containsString; import java.util.List; @@ -113,7 +112,6 @@ public void testCreateRemoteMessageAllProperties() { requestBody.pullReplicas = 789; requestBody.createReplicas = true; requestBody.nodeSet = List.of("node1", "node2"); - requestBody.waitForFinalState = true; requestBody.followAliases = true; requestBody.async = "someAsyncId"; requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2"); @@ -121,7 +119,7 @@ public void testCreateRemoteMessageAllProperties() { final var remoteMessage = CreateShard.createRemoteMessage("someCollectionName", requestBody).getProperties(); - assertEquals(13, remoteMessage.size()); + assertEquals(12, remoteMessage.size()); assertEquals("createshard", remoteMessage.get(QUEUE_OPERATION)); assertEquals("someCollectionName", remoteMessage.get(COLLECTION)); assertEquals("someShardName", remoteMessage.get(SHARD_ID_PROP)); @@ -130,7 +128,6 @@ public void testCreateRemoteMessageAllProperties() { assertEquals(456, remoteMessage.get(TLOG_REPLICAS)); assertEquals(789, remoteMessage.get(PULL_REPLICAS)); assertEquals("node1,node2", remoteMessage.get(CREATE_NODE_SET_PARAM)); - assertEquals(true, remoteMessage.get(WAIT_FOR_FINAL_STATE)); assertEquals(true, remoteMessage.get(FOLLOW_ALIASES)); assertEquals("someAsyncId", remoteMessage.get(ASYNC)); assertEquals("propVal1", remoteMessage.get("property.propName1")); @@ -147,7 +144,6 @@ public void testCanConvertV1ParamsToV2RequestBody() { v1Params.set(TLOG_REPLICAS, 456); v1Params.set(PULL_REPLICAS, 789); v1Params.add(CREATE_NODE_SET_PARAM, "node1,node2"); - v1Params.set(WAIT_FOR_FINAL_STATE, true); v1Params.set(FOLLOW_ALIASES, true); v1Params.add(ASYNC, "someAsyncId"); v1Params.add("property.propName1", "propVal1"); @@ -162,7 +158,6 @@ public void testCanConvertV1ParamsToV2RequestBody() { assertEquals(Integer.valueOf(789), requestBody.pullReplicas); assertNull(requestBody.createReplicas); assertEquals(List.of("node1", "node2"), requestBody.nodeSet); - assertEquals(Boolean.TRUE, requestBody.waitForFinalState); assertEquals(Boolean.TRUE, requestBody.followAliases); assertEquals("someAsyncId", requestBody.async); assertEquals("propVal1", requestBody.properties.get("propName1")); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java index 85f0ffc1d3c..3b0a333a9d7 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/MigrateReplicasAPITest.java @@ -81,17 +81,15 @@ public void setUp() throws Exception { @Test public void testCreatesValidOverseerMessage() throws Exception { MigrateReplicasRequestBody requestBody = - new MigrateReplicasRequestBody( - Set.of("demoSourceNode"), Set.of("demoTargetNode"), false, "async"); + new MigrateReplicasRequestBody(Set.of("demoSourceNode"), Set.of("demoTargetNode"), "async"); migrateReplicasAPI.migrateReplicas(requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); final ZkNodeProps createdMessage = messageCapturer.getValue(); final Map createdMessageProps = createdMessage.getProperties(); - assertEquals(5, createdMessageProps.size()); + assertEquals(4, createdMessageProps.size()); assertEquals(Set.of("demoSourceNode"), createdMessageProps.get("sourceNodes")); assertEquals(Set.of("demoTargetNode"), createdMessageProps.get("targetNodes")); - assertEquals(false, createdMessageProps.get("waitForFinalState")); assertEquals("async", createdMessageProps.get("async")); assertEquals("migrate_replicas", createdMessageProps.get("operation")); } @@ -99,7 +97,7 @@ public void testCreatesValidOverseerMessage() throws Exception { @Test public void testNoTargetNodes() throws Exception { MigrateReplicasRequestBody requestBody = - new MigrateReplicasRequestBody(Set.of("demoSourceNode"), null, null, null); + new MigrateReplicasRequestBody(Set.of("demoSourceNode"), null, null); migrateReplicasAPI.migrateReplicas(requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); @@ -113,11 +111,10 @@ public void testNoTargetNodes() throws Exception { @Test public void testNoSourceNodesThrowsError() throws Exception { MigrateReplicasRequestBody requestBody1 = - new MigrateReplicasRequestBody( - Collections.emptySet(), Set.of("demoTargetNode"), null, null); + new MigrateReplicasRequestBody(Collections.emptySet(), Set.of("demoTargetNode"), null); assertThrows(SolrException.class, () -> migrateReplicasAPI.migrateReplicas(requestBody1)); MigrateReplicasRequestBody requestBody2 = - new MigrateReplicasRequestBody(null, Set.of("demoTargetNode"), null, null); + new MigrateReplicasRequestBody(null, Set.of("demoTargetNode"), null); assertThrows(SolrException.class, () -> migrateReplicasAPI.migrateReplicas(requestBody2)); } } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ReplaceNodeAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ReplaceNodeAPITest.java index a325da55e7d..079e401b715 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/ReplaceNodeAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ReplaceNodeAPITest.java @@ -77,16 +77,15 @@ public void setUp() throws Exception { @Test public void testCreatesValidOverseerMessage() throws Exception { - final var requestBody = new ReplaceNodeRequestBody("demoTargetNode", false, "async"); + final var requestBody = new ReplaceNodeRequestBody("demoTargetNode", "async"); replaceNodeApi.replaceNode("demoSourceNode", requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); final ZkNodeProps createdMessage = messageCapturer.getValue(); final Map createdMessageProps = createdMessage.getProperties(); - assertEquals(5, createdMessageProps.size()); + assertEquals(4, createdMessageProps.size()); assertEquals("demoSourceNode", createdMessageProps.get("sourceNode")); assertEquals("demoTargetNode", createdMessageProps.get("targetNode")); - assertEquals(false, createdMessageProps.get("waitForFinalState")); assertEquals("async", createdMessageProps.get("async")); assertEquals("replacenode", createdMessageProps.get("operation")); } @@ -105,7 +104,7 @@ public void testRequestBodyCanBeOmittedAltogether() throws Exception { @Test public void testOptionalValuesNotAddedToRemoteMessageIfNotProvided() throws Exception { - final var requestBody = new ReplaceNodeRequestBody("demoTargetNode", null, null); + final var requestBody = new ReplaceNodeRequestBody("demoTargetNode", null); replaceNodeApi.replaceNode("demoSourceNode", requestBody); verify(mockCommandRunner).runCollectionCommand(messageCapturer.capture(), any(), anyLong()); @@ -116,10 +115,6 @@ public void testOptionalValuesNotAddedToRemoteMessageIfNotProvided() throws Exce assertEquals("demoSourceNode", createdMessageProps.get("sourceNode")); assertEquals("demoTargetNode", createdMessageProps.get("targetNode")); assertEquals("replacenode", createdMessageProps.get("operation")); - assertFalse( - "Expected message to not contain value for waitForFinalState: " - + createdMessageProps.get("waitForFinalState"), - createdMessageProps.containsKey("waitForFinalState")); assertFalse( "Expected message to not contain value for async: " + createdMessageProps.get("async"), createdMessageProps.containsKey("async")); diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc index 90006a03e94..c62cbc33e14 100644 --- a/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc +++ b/solr/solr-ref-guide/modules/deployment-guide/pages/collection-management.adoc @@ -259,16 +259,6 @@ Overriding entries can result in unusable collections. Altering these entries by specifying `property._name_=_value_` is an expert-level option and should only be used if you have a thorough understanding of the consequences. ==== -`waitForFinalState`:: -+ -[%autowidth,frame=none] -|=== -|Optional |Default: none -|=== -+ -If `true`, the request will complete only when all affected replicas become active. -The default is `false`, which means that the API will return the status of the single action, which may be before the new replica is online and active. - `alias`:: + [%autowidth,frame=none] @@ -703,7 +693,7 @@ To delete an existing collection property: [source,bash] ---- -curl -X DELETE http://localhost:8983/api/collections/techproducts_v2/properties/foo +curl -X DELETE http://localhost:8983/api/collections/techproducts_v2/properties/foo ---- ==== ====== @@ -1590,7 +1580,7 @@ s|Required |Default: none What to name the backup that is created. Provided as a query parameter for v1 requests, or as a path segment for v2 requests. + -For incremental backups, the backup name should be reused to add new backup points to the existing backup. For non-incremental backups (deprecated), this name is checked to ensure it doesn't already exist, and an error message is raised if it does. +For incremental backups, the backup name should be reused to add new backup points to the existing backup. For non-incremental backups (deprecated), this name is checked to ensure it doesn't already exist, and an error message is raised if it does. `location`:: +