[
https://issues.apache.org/jira/browse/SOLR-8323?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15279790#comment-15279790
]
ASF GitHub Bot commented on SOLR-8323:
--------------------------------------
Github user romseygeek commented on a diff in the pull request:
https://github.com/apache/lucene-solr/pull/32#discussion_r62810535
--- Diff:
solr/solrj/src/test/org/apache/solr/common/cloud/TestCollectionStateWatchers.java
---
@@ -0,0 +1,235 @@
+package org.apache.solr.common.cloud;
+
+/*
+ * 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.
+ */
+
+import java.util.HashMap;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.cloud.SolrCloudTestCase;
+import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.SolrjNamedThreadFactory;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+
+public class TestCollectionStateWatchers extends SolrCloudTestCase {
+
+ private static final int CLUSTER_SIZE = 4;
+
+ private static final ExecutorService executor =
ExecutorUtil.newMDCAwareCachedThreadPool(
+ new SolrjNamedThreadFactory("backgroundWatchers")
+ );
+
+ private static final int MAX_WAIT_TIMEOUT = 30;
+
+ @BeforeClass
+ public static void startCluster() throws Exception {
+ configureCluster(CLUSTER_SIZE)
+ .addConfig("config",
getFile("solrj/solr/collection1/conf").toPath())
+ .configure();
+ }
+
+ @AfterClass
+ public static void shutdownBackgroundExecutors() {
+ executor.shutdown();
+ }
+
+ @Before
+ public void prepareCluster() throws Exception {
+ int missingServers = CLUSTER_SIZE -
cluster.getJettySolrRunners().size();
+ for (int i = 0; i < missingServers; i++) {
+ cluster.startJettySolrRunner();
+ }
+ cluster.waitForAllNodes(30);
+ }
+
+ private static Future<Boolean> waitInBackground(String collection, long
timeout, TimeUnit unit,
+ CollectionStatePredicate
predicate) {
+ return executor.submit(() -> {
+ try {
+ cluster.getSolrClient().waitForState(collection, timeout, unit,
predicate);
+ } catch (InterruptedException | TimeoutException e) {
+ return Boolean.FALSE;
+ }
+ return Boolean.TRUE;
+ });
+ }
+
+
+ @Test
+ public void testSimpleCollectionWatch() throws Exception {
+
+ CloudSolrClient client = cluster.getSolrClient();
+ cluster.createCollection("testcollection", CLUSTER_SIZE, 1, "config",
new HashMap<>());
+
+ client.waitForState("testcollection", MAX_WAIT_TIMEOUT,
TimeUnit.SECONDS, DocCollection::isFullyActive);
+
+ // shutdown a node and check that we get notified about the change
+ final AtomicInteger nodeCount = new AtomicInteger(0);
+ final CountDownLatch latch = new CountDownLatch(1);
+ client.registerCollectionStateWatcher("testcollection", (liveNodes,
collectionState) -> {
+ // we can't just count liveNodes here, because that's updated by a
separate watcher,
+ // and it may be the case that we're triggered by a node setting
itself to DOWN before
+ // the liveNodes watcher is called
+ for (Slice slice : collectionState) {
+ for (Replica replica : slice) {
+ if (replica.isActive(liveNodes))
+ nodeCount.incrementAndGet();
+ }
+ }
+ latch.countDown();
+ });
+
+
cluster.stopJettySolrRunner(random().nextInt(cluster.getJettySolrRunners().size()));
+ assertTrue("CollectionStateWatcher was never notified of cluster
change", latch.await(MAX_WAIT_TIMEOUT, TimeUnit.SECONDS));
+
+ assertThat(nodeCount.intValue(), is(3));
+
+ }
+
+ @Test
+ public void testWaitForStateChecksCurrentState() throws Exception {
+
+ CloudSolrClient client = cluster.getSolrClient();
+ cluster.createCollection("waitforstate", 1, 1, "config", new
HashMap<>());
+
+ client.waitForState("waitforstate", MAX_WAIT_TIMEOUT,
TimeUnit.SECONDS, DocCollection::isFullyActive);
+
+ // several goes, to check that we're not getting delayed state changes
+ for (int i = 0; i < 10; i++) {
+ try {
+ client.waitForState("waitforstate", 1, TimeUnit.SECONDS,
DocCollection::isFullyActive);
+ }
+ catch (TimeoutException e) {
+ fail("waitForState should return immediately if the predicate is
already satisfied");
+ }
+ }
+
+ }
+
+ @Test
+ public void testCanWatchForNonexistantCollection() throws Exception {
--- End diff --
If there's already a watch set, then it won't be fired. If there's no
watch set, then it will be fired by StateWatcher#refreshAndWatch().
> Add CollectionWatcher API to ZkStateReader
> ------------------------------------------
>
> Key: SOLR-8323
> URL: https://issues.apache.org/jira/browse/SOLR-8323
> Project: Solr
> Issue Type: Improvement
> Affects Versions: 6.0
> Reporter: Alan Woodward
> Assignee: Alan Woodward
> Attachments: SOLR-8323.patch, SOLR-8323.patch, SOLR-8323.patch,
> SOLR-8323.patch
>
>
> An API to watch for changes to collection state would be a generally useful
> thing, both internally and for client use.
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]