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

sdanilov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new c4b214c7a0 IGNITE-18710 Make default for delay to remove from logical 
topology non-zero (#1636)
c4b214c7a0 is described below

commit c4b214c7a0166692b299b4427b77396c90b68604
Author: Roman Puchkovskiy <[email protected]>
AuthorDate: Tue Feb 7 13:15:48 2023 +0400

    IGNITE-18710 Make default for delay to remove from logical topology 
non-zero (#1636)
---
 .../ignite/internal/cli/IntegrationTestBase.java   |  7 +++--
 .../repl/executor/ItIgnitePicocliCommandsTest.java |  2 +-
 .../management/BaseItClusterManagementTest.java    |  2 +-
 .../management/ClusterManagementGroupManager.java  |  1 +
 .../ClusterManagementConfigurationSchema.java      |  3 +-
 .../internal/AbstractClusterIntegrationTest.java   | 31 +++++++++++++++++--
 .../java/org/apache/ignite/internal/Cluster.java   | 33 +++++++++++++++++---
 .../internal/compute/ItLogicalTopologyTest.java    | 36 ++++++++++++++++++++--
 8 files changed, 98 insertions(+), 17 deletions(-)

diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/IntegrationTestBase.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/IntegrationTestBase.java
index b809518b6a..eca4c7a2f3 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/IntegrationTestBase.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/IntegrationTestBase.java
@@ -101,8 +101,8 @@ public class IntegrationTestBase extends 
BaseIgniteAbstractTest {
             + "  }\n"
             + "}";
 
-    /** Template for node bootstrap config with Scalecube settings for fast 
failure detection. */
-    protected static final String FAST_SWIM_NODE_BOOTSTRAP_CFG_TEMPLATE = "{\n"
+    /** Template for node bootstrap config with Scalecube and Logical Topology 
settings for fast failure detection. */
+    protected static final String 
FAST_FAILURE_DETECTION_NODE_BOOTSTRAP_CFG_TEMPLATE = "{\n"
             + "  network: {\n"
             + "    port: {},\n"
             + "    nodeFinder: {\n"
@@ -117,7 +117,8 @@ public class IntegrationTestBase extends 
BaseIgniteAbstractTest {
             + "        gossipInterval: 10\n"
             + "      },\n"
             + "    }\n"
-            + "  }\n"
+            + "  },"
+            + "  cluster.failoverTimeout: 100\n"
             + "}";
 
     /** Futures that are going to be completed when all nodes are started and 
the cluster is initialized. */
diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
index 72aaa3d807..122a9befcc 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/core/repl/executor/ItIgnitePicocliCommandsTest.java
@@ -89,7 +89,7 @@ public class ItIgnitePicocliCommandsTest extends 
CliCommandTestInitializedIntegr
 
     @Override
     protected String nodeBootstrapConfigTemplate() {
-        return FAST_SWIM_NODE_BOOTSTRAP_CFG_TEMPLATE;
+        return FAST_FAILURE_DETECTION_NODE_BOOTSTRAP_CFG_TEMPLATE;
     }
 
     @BeforeEach
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
index d24d5070eb..0f5cb7359b 100644
--- 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/BaseItClusterManagementTest.java
@@ -44,7 +44,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
 public class BaseItClusterManagementTest extends BaseIgniteAbstractTest {
     private static final int PORT_BASE = 10000;
 
-    @InjectConfiguration
+    @InjectConfiguration("mock.failoverTimeout: 100")
     private static ClusterManagementConfiguration cmgConfiguration;
 
     @InjectConfiguration
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
index 70767928da..bf0c7e8ff5 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
@@ -386,6 +386,7 @@ public class ClusterManagementGroupManager implements 
IgniteComponent {
                             .filter(node -> 
!physicalTopologyIds.contains(node.id()))
                             .collect(toUnmodifiableSet());
 
+                    // TODO: IGNITE-18681 - respect removal timeout.
                     return nodesToRemove.isEmpty() ? completedFuture(null) : 
service.removeFromCluster(nodesToRemove);
                 })
                 .thenApply(v -> service);
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationSchema.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationSchema.java
index ab38f24f27..4dc156b411 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationSchema.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/configuration/ClusterManagementConfigurationSchema.java
@@ -38,8 +38,7 @@ public class ClusterManagementConfigurationSchema {
      */
     @Value(hasDefault = true)
     @Range(min = 0)
-    // TODO: IGNITE-18630 - change this to a sensible default.
-    public long failoverTimeout = 0;
+    public long failoverTimeout = TimeUnit.SECONDS.toMillis(30);
 
     /** Maximum amount of time a validated node that has not yet completed the 
join is allowed to remain validated (ms). */
     @Value(hasDefault = true)
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/AbstractClusterIntegrationTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/AbstractClusterIntegrationTest.java
index 0f18443650..6a891e4f39 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/AbstractClusterIntegrationTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/AbstractClusterIntegrationTest.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal;
 
 import static 
org.apache.ignite.internal.sql.engine.util.CursorUtils.getAllFromCursor;
 
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.nio.file.Path;
 import java.util.List;
 import org.apache.ignite.Ignite;
@@ -33,6 +35,7 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.TestInfo;
 import org.junit.jupiter.api.Timeout;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.platform.commons.support.ReflectionSupport;
 
 /**
  * Abstract integration test that starts and stops a cluster.
@@ -55,8 +58,8 @@ public abstract class AbstractClusterIntegrationTest extends 
BaseIgniteAbstractT
             + "  }\n"
             + "}";
 
-    /** Template for node bootstrap config with Scalecube settings for fast 
failure detection. */
-    protected static final String FAST_SWIM_NODE_BOOTSTRAP_CFG_TEMPLATE = "{\n"
+    /** Template for node bootstrap config with Scalecube and Logical Topology 
settings for fast failure detection. */
+    protected static final String 
FAST_FAILURE_DETECTION_NODE_BOOTSTRAP_CFG_TEMPLATE = "{\n"
             + "  network: {\n"
             + "    port: {},\n"
             + "    nodeFinder: {\n"
@@ -71,7 +74,8 @@ public abstract class AbstractClusterIntegrationTest extends 
BaseIgniteAbstractT
             + "        gossipInterval: 10\n"
             + "      },\n"
             + "    }\n"
-            + "  }\n"
+            + "  },"
+            + "  cluster.failoverTimeout: 100\n"
             + "}";
 
     protected Cluster cluster;
@@ -109,6 +113,16 @@ public abstract class AbstractClusterIntegrationTest 
extends BaseIgniteAbstractT
         cluster.startAndInit(initialNodes());
     }
 
+    private String invokeArglessMethod(Class<?> testClass, String methodName) {
+        Method method = ReflectionSupport.findMethod(testClass, 
methodName).orElseThrow();
+
+        if (!Modifier.isStatic(method.getModifiers())) {
+            throw new IllegalStateException(methodName + " is expected to be 
static");
+        }
+
+        return (String) ReflectionSupport.invokeMethod(method, null);
+    }
+
     @AfterEach
     @Timeout(60)
     void shutdownCluster() {
@@ -143,6 +157,17 @@ public abstract class AbstractClusterIntegrationTest 
extends BaseIgniteAbstractT
         return cluster.startNode(nodeIndex);
     }
 
+    /**
+     * Starts an Ignite node with the given index.
+     *
+     * @param nodeIndex Zero-based index (used to build node name).
+     * @param nodeBootstrapConfigTemplate Bootstrap config template to use for 
this node.
+     * @return Started Ignite node.
+     */
+    protected final IgniteImpl startNode(int nodeIndex, String 
nodeBootstrapConfigTemplate) {
+        return cluster.startNode(nodeIndex, nodeBootstrapConfigTemplate);
+    }
+
     /**
      * Stops a node by index.
      *
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/Cluster.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/Cluster.java
index 67bfde67c5..69c4a61147 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/Cluster.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/Cluster.java
@@ -88,7 +88,7 @@ public class Cluster {
 
     private final Path workDir;
 
-    private final String nodeBootstrapConfigTemplate;
+    private final String defaultNodeBootstrapConfigTemplate;
 
     /** Cluster nodes. */
     private final List<IgniteImpl> nodes = new CopyOnWriteArrayList<>();
@@ -110,10 +110,10 @@ public class Cluster {
     /**
      * Creates a new cluster with the given bootstrap config.
      */
-    public Cluster(TestInfo testInfo, Path workDir, String 
nodeBootstrapConfigTemplate) {
+    public Cluster(TestInfo testInfo, Path workDir, String 
defaultNodeBootstrapConfigTemplate) {
         this.testInfo = testInfo;
         this.workDir = workDir;
-        this.nodeBootstrapConfigTemplate = nodeBootstrapConfigTemplate;
+        this.defaultNodeBootstrapConfigTemplate = 
defaultNodeBootstrapConfigTemplate;
     }
 
     /**
@@ -142,12 +142,23 @@ public class Cluster {
     }
 
     /**
-     * Start a cluster node and return its startup future.
+     * Starts a cluster node with the default bootstrap config template and 
returns its startup future.
      *
      * @param nodeIndex Index of the nodex to start.
      * @return Future that will be completed when the node starts.
      */
     public CompletableFuture<IgniteImpl> startClusterNode(int nodeIndex) {
+        return startClusterNode(nodeIndex, defaultNodeBootstrapConfigTemplate);
+    }
+
+    /**
+     * Starts a cluster node and returns its startup future.
+     *
+     * @param nodeIndex Index of the nodex to start.
+     * @param nodeBootstrapConfigTemplate Bootstrap config template to use for 
this node.
+     * @return Future that will be completed when the node starts.
+     */
+    public CompletableFuture<IgniteImpl> startClusterNode(int nodeIndex, 
String nodeBootstrapConfigTemplate) {
         String nodeName = testNodeName(testInfo, nodeIndex);
 
         String config = 
IgniteStringFormatter.format(nodeBootstrapConfigTemplate, BASE_PORT + 
nodeIndex, CONNECT_NODE_ADDR);
@@ -204,10 +215,22 @@ public class Cluster {
      *     is not initialized, the node is returned in a state in which it is 
ready to join the cluster).
      */
     public IgniteImpl startNode(int index) {
+        return startNode(index, defaultNodeBootstrapConfigTemplate);
+    }
+
+    /**
+     * Starts a new node with the given index.
+     *
+     * @param index Node index.
+     * @param nodeBootstrapConfigTemplate Bootstrap config template to use for 
this node.
+     * @return Started node (if the cluster is already initialized, the node 
is returned when it joins the cluster; if it
+     *     is not initialized, the node is returned in a state in which it is 
ready to join the cluster).
+     */
+    public IgniteImpl startNode(int index, String nodeBootstrapConfigTemplate) 
{
         IgniteImpl newIgniteNode;
 
         try {
-            newIgniteNode = startClusterNode(index).get(10, TimeUnit.SECONDS);
+            newIgniteNode = startClusterNode(index, 
nodeBootstrapConfigTemplate).get(10, TimeUnit.SECONDS);
         } catch (InterruptedException e) {
             Thread.currentThread().interrupt();
 
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/compute/ItLogicalTopologyTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/compute/ItLogicalTopologyTest.java
index dc25c73540..a4e05a3d7e 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/compute/ItLogicalTopologyTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/compute/ItLogicalTopologyTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.compute;
 
 import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -27,10 +28,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.AbstractClusterIntegrationTest;
+import org.apache.ignite.internal.Cluster.NodeKnockout;
 import org.apache.ignite.internal.app.IgniteImpl;
+import 
org.apache.ignite.internal.cluster.management.configuration.ClusterManagementConfiguration;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyEventListener;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import org.apache.ignite.internal.network.message.ScaleCubeMessage;
@@ -64,7 +69,7 @@ class ItLogicalTopologyTest extends 
AbstractClusterIntegrationTest {
 
     @Override
     protected String getNodeBootstrapConfigTemplate() {
-        return FAST_SWIM_NODE_BOOTSTRAP_CFG_TEMPLATE;
+        return FAST_FAILURE_DETECTION_NODE_BOOTSTRAP_CFG_TEMPLATE;
     }
 
     @Test
@@ -143,7 +148,6 @@ class ItLogicalTopologyTest extends 
AbstractClusterIntegrationTest {
                 if (appearedNode.name().equals(secondIgnite.name())) {
                     secondIgniteAppeared.countDown();
                 }
-
             }
         });
 
@@ -170,6 +174,34 @@ class ItLogicalTopologyTest extends 
AbstractClusterIntegrationTest {
         assertTrue(secondIgniteDisappeared.await(10, TimeUnit.SECONDS), "Did 
not see second node leaving in time");
     }
 
+    @Test
+    void nodeDoesNotLeaveLogicalTopologyImmediatelyAfterBeingLostBySwim() 
throws Exception {
+        IgniteImpl entryNode = node(0);
+
+        setInfiniteClusterFailoverTimeout(entryNode);
+
+        startNode(1);
+
+        entryNode.logicalTopologyService().addEventListener(listener);
+
+        // Knock the node out without allowing it to say good bye.
+        cluster.knockOutNode(1, NodeKnockout.PARTITION_NETWORK);
+
+        // 1 second is usually insufficient on my machine to get an event, 
even if it's produced. On the CI we
+        // should probably account for spurious delays due to other processes, 
hence 2 seconds.
+        waitForCondition(() -> !events.isEmpty(), 2_000);
+
+        assertThat(events, is(empty()));
+    }
+
+    private static void setInfiniteClusterFailoverTimeout(IgniteImpl node)
+            throws InterruptedException, ExecutionException, TimeoutException {
+        
node.nodeConfiguration().getConfiguration(ClusterManagementConfiguration.KEY)
+                .failoverTimeout()
+                .update(Long.MAX_VALUE)
+                .get(10, TimeUnit.SECONDS);
+    }
+
     private static class Event {
         private final boolean appeared;
         private final ClusterNode node;

Reply via email to