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

sk0x50 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 315e917a0f6 IGNITE-28094 Revert "IGNITE-27906 Remove creating 
redundant collections (#7628)" (#7728)
315e917a0f6 is described below

commit 315e917a0f67d6699a11a9b110849a66470ba0fe
Author: Slava Koptilin <[email protected]>
AuthorDate: Fri Mar 6 16:16:42 2026 +0200

    IGNITE-28094 Revert "IGNITE-27906 Remove creating redundant collections 
(#7628)" (#7728)
---
 .../compaction/CatalogCompactionRunner.java        | 12 ++-
 .../cluster/management/ItClusterManagerTest.java   |  7 +-
 .../management/raft/ItCmgRaftServiceTest.java      |  2 +-
 .../metrics/ClusterTopologyMetricsSource.java      |  2 +-
 .../management/raft/CmgRaftGroupListener.java      |  8 +-
 .../cluster/management/raft/CmgRaftService.java    |  3 +-
 .../cluster/management/raft/ValidationManager.java |  2 +-
 .../management/topology/LogicalTopologyImpl.java   | 13 +--
 .../topology/api/LogicalTopologySnapshot.java      | 96 ++--------------------
 .../api/LogicalTopologySnapshotSerializer.java     |  2 +-
 .../topology/LogicalTopologyImplTest.java          |  6 +-
 .../api/LogicalTopologySnapshotSerializerTest.java |  3 +-
 .../internal/cluster/management/MockNode.java      |  3 +-
 .../internal/deployunit/DefaultNodeCallback.java   |  5 +-
 .../internal/deployunit/DeploymentManagerImpl.java |  6 +-
 .../ignite/internal/deployunit/NodesToDeploy.java  | 26 ++++--
 .../metastore/ClusterEventCallbackImpl.java        | 13 ++-
 .../distributionzones/ItDataNodesManagerTest.java  |  2 +-
 .../rebalance/ItRebalanceDistributedTest.java      |  2 +-
 .../distributionzones/DistributionZoneManager.java |  2 +-
 .../ItMetaStorageMultipleNodesVsStorageTest.java   |  5 +-
 .../replicator/ItAbstractColocationTest.java       |  2 +-
 .../internal/placementdriver/TopologyTracker.java  | 11 ++-
 .../negotiation/LeaseAgreement.java                |  7 +-
 .../rest/cluster/ItDataNodesControllerTest.java    |  2 +-
 .../runner/app/ItIgniteNodeRestartTest.java        | 10 ++-
 .../org/apache/ignite/internal/app/IgniteImpl.java |  3 +-
 .../internal/sql/api/ItSqlCreateZoneTest.java      |  8 +-
 .../engine/exec/mapping/MappingServiceImpl.java    |  8 +-
 .../ddl/ClusterWideStorageProfileValidator.java    |  2 +-
 .../engine/statistic/StatisticAggregatorImpl.java  |  5 +-
 .../engine/framework/ClusterServiceFactory.java    | 10 ++-
 .../disaster/system/ItCmgDisasterRecoveryTest.java |  3 +-
 .../system/ItSystemGroupDisasterRecoveryTest.java  |  2 +-
 ...ilablePartitionsRecoveryByFilterUpdateTest.java |  5 +-
 35 files changed, 141 insertions(+), 157 deletions(-)

diff --git 
a/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
 
b/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
index f1d0de10000..c4521564770 100644
--- 
a/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
+++ 
b/modules/catalog-compaction/src/main/java/org/apache/ignite/internal/catalog/compaction/CatalogCompactionRunner.java
@@ -57,6 +57,7 @@ import 
org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogIndexStatus;
 import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
 import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyService;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.distributionzones.rebalance.RebalanceMinimumRequiredTimeProvider;
@@ -485,7 +486,7 @@ public class CatalogCompactionRunner implements 
IgniteComponent {
                     }
 
                     Set<String> requiredNodes = result.getSecond();
-                    List<String> missingNodes = missingNodes(requiredNodes, 
topologySnapshot);
+                    List<String> missingNodes = missingNodes(requiredNodes, 
topologySnapshot.nodes());
 
                     if (!missingNodes.isEmpty()) {
                         LOG.info("Catalog compaction aborted due to missing 
cluster members [nodes={}].", missingNodes);
@@ -639,8 +640,13 @@ public class CatalogCompactionRunner implements 
IgniteComponent {
         return executor;
     }
 
-    private static List<String> missingNodes(Set<String> requiredNodes, 
LogicalTopologySnapshot logicalTopologySnapshot) {
-        return 
requiredNodes.stream().filter(not(logicalTopologySnapshot::hasNode)).collect(Collectors.toList());
+    private static List<String> missingNodes(Set<String> requiredNodes, 
Collection<LogicalNode> logicalTopologyNodes) {
+        Set<String> logicalNodeIds = logicalTopologyNodes
+                .stream()
+                .map(InternalClusterNode::name)
+                .collect(Collectors.toSet());
+
+        return 
requiredNodes.stream().filter(not(logicalNodeIds::contains)).collect(Collectors.toList());
     }
 
     private CompletableFuture<Void> invokeOnLocalReplicas(long txBeginTime, 
UUID localNodeId, ObjectIterator<Entry> entryIterator) {
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
index edcfab41009..1b8123071fa 100644
--- 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/ItClusterManagerTest.java
@@ -35,7 +35,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -639,7 +638,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
         MockNode nonCmgNode = cluster.get(1);
         LogicalTopologyImpl nonCmgTopology = 
nonCmgNode.clusterManager().logicalTopologyImpl();
 
-        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().size() == 2, 10_000));
+        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().nodes().size() == 2, 10_000));
     }
 
     @Test
@@ -656,7 +655,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
 
         LogicalTopologyImpl nonCmgTopology = 
nonCmgNode.clusterManager().logicalTopologyImpl();
 
-        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().size() == 2, 10_000));
+        assertTrue(waitForCondition(() -> 
nonCmgTopology.getLogicalTopology().nodes().size() == 2, 10_000));
     }
 
     @Test
@@ -706,7 +705,7 @@ public class ItClusterManagerTest extends 
BaseItClusterManagementTest {
 
     private void waitForLogicalTopology() throws InterruptedException {
         assertTrue(waitForCondition(() -> {
-            CompletableFuture<Collection<LogicalNode>> logicalTopology = 
cluster.get(0).logicalTopologyNodes();
+            CompletableFuture<Set<LogicalNode>> logicalTopology = 
cluster.get(0).logicalTopologyNodes();
 
             assertThat(logicalTopology, willCompleteSuccessfully());
 
diff --git 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
index 3d5b72cd020..e4c0d086467 100644
--- 
a/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
+++ 
b/modules/cluster-management/src/integrationTest/java/org/apache/ignite/internal/cluster/management/raft/ItCmgRaftServiceTest.java
@@ -196,7 +196,7 @@ public class ItCmgRaftServiceTest extends 
BaseIgniteAbstractTest {
             return clusterService.topologyService().localMember();
         }
 
-        private CompletableFuture<Collection<LogicalNode>> 
logicalTopologyNodes() {
+        private CompletableFuture<Set<LogicalNode>> logicalTopologyNodes() {
             return 
raftService.logicalTopology().thenApply(LogicalTopologySnapshot::nodes);
         }
 
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
index 2bf0f7af9a4..cafe1350ff7 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/metrics/ClusterTopologyMetricsSource.java
@@ -110,7 +110,7 @@ public class ClusterTopologyMetricsSource extends 
AbstractMetricSource<ClusterTo
         private final IntGauge clusterSize = new IntGauge(
                 "TotalNodes",
                 "Number of nodes in the logical topology",
-                () -> logicalTopology.getLogicalTopology().size());
+                () -> logicalTopology.getLogicalTopology().nodes().size());
 
         private final UuidGauge clusterId = new UuidGauge(
                 "ClusterId",
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
index f6b9731871e..0e34814bb8c 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftGroupListener.java
@@ -25,7 +25,6 @@ import static 
org.apache.ignite.internal.util.IgniteUtils.capacity;
 
 import java.io.Serializable;
 import java.nio.file.Path;
-import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -159,7 +158,7 @@ public class CmgRaftGroupListener implements 
RaftGroupListener {
 
     private HashSet<LogicalNode> getValidatedNodes() {
         List<LogicalNode> validatedNodes = storageManager.getValidatedNodes();
-        Collection<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
+        Set<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
 
         var result = new HashSet<LogicalNode>(capacity(validatedNodes.size() + 
logicalTopologyNodes.size()));
 
@@ -262,7 +261,10 @@ public class CmgRaftGroupListener implements 
RaftGroupListener {
     }
 
     private ValidationResult validateNode(JoinRequestCommand command) {
-        Optional<LogicalNode> previousVersion = 
logicalTopology.getLogicalTopology().node(command.node().name());
+        Optional<LogicalNode> previousVersion = 
logicalTopology.getLogicalTopology().nodes()
+                .stream()
+                .filter(n -> n.name().equals(command.node().name()))
+                .findAny();
 
         if (previousVersion.isPresent()) {
             LogicalNode previousNode = previousVersion.get();
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
index 94f07fb3e3f..acd0c1e042d 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/CmgRaftService.java
@@ -325,7 +325,8 @@ public class CmgRaftService implements ManuallyCloseable {
 
         Set<String> currentPeers = nodeNames();
 
-        Set<String> newLearners = 
logicalTopology.getLogicalTopology().nodeNames().stream()
+        Set<String> newLearners = 
logicalTopology.getLogicalTopology().nodes().stream()
+                .map(InternalClusterNode::name)
                 .filter(name -> !currentPeers.contains(name))
                 .collect(toSet());
 
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
index 46787f05551..35b3bad6097 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/raft/ValidationManager.java
@@ -128,7 +128,7 @@ public class ValidationManager {
     }
 
     private boolean isColocationEnabledMatched(boolean 
joiningNodeColocationEnabled) {
-        Collection<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
+        Set<LogicalNode> logicalTopologyNodes = 
logicalTopology.getLogicalTopology().nodes();
 
         return logicalTopologyNodes.isEmpty()
                 || isColocationEnabled(logicalTopologyNodes.iterator().next()) 
== joiningNodeColocationEnabled;
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
index 4dcf96861e2..855a695fb7b 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImpl.java
@@ -19,11 +19,12 @@ package 
org.apache.ignite.internal.cluster.management.topology;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Comparator.comparing;
+import static java.util.function.Function.identity;
 import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
 import static org.apache.ignite.internal.util.ExceptionUtils.hasCause;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -78,7 +79,6 @@ public class LogicalTopologyImpl implements LogicalTopology {
     }
 
     private LogicalTopologySnapshot readLogicalTopology() {
-        // TODO https://issues.apache.org/jira/browse/IGNITE-28066
         byte[] bytes = storage.get(LOGICAL_TOPOLOGY_KEY);
 
         return bytes == null ? LogicalTopologySnapshot.INITIAL
@@ -99,7 +99,8 @@ public class LogicalTopologyImpl implements LogicalTopology {
     public void putNode(LogicalNode nodeToPut) {
         LogicalTopologySnapshot snapshot = readLogicalTopology();
 
-        Map<String, LogicalNode> mapByName = new 
HashMap<>(snapshot.nodesByName());
+        Map<String, LogicalNode> mapByName = snapshot.nodes().stream()
+                .collect(toMap(LogicalNode::name, identity()));
 
         Runnable fireRemovalTask = null;
 
@@ -166,7 +167,8 @@ public class LogicalTopologyImpl implements LogicalTopology 
{
     public void removeNodes(Set<LogicalNode> nodesToRemove) {
         LogicalTopologySnapshot snapshot = readLogicalTopology();
 
-        Map<UUID, LogicalNode> mapById = new HashMap<>(snapshot.nodesById());
+        Map<UUID, LogicalNode> mapById = snapshot.nodes().stream()
+                .collect(toMap(LogicalNode::id, identity()));
 
         // Removing in a well-defined order to make sure that a command 
produces an identical sequence of events in each CMG listener.
         List<LogicalNode> sortedNodesToRemove = nodesToRemove.stream()
@@ -199,7 +201,8 @@ public class LogicalTopologyImpl implements LogicalTopology 
{
 
     @Override
     public boolean isNodeInLogicalTopology(LogicalNode needle) {
-        return readLogicalTopology().hasNode(needle.id());
+        return readLogicalTopology().nodes().stream()
+                .anyMatch(node -> node.id().equals(needle.id()));
     }
 
     private void fireNodeJoined(LogicalNode appearedNode, 
LogicalTopologySnapshot snapshot) {
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
index b3a8931e74f..79b29d93d37 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshot.java
@@ -18,14 +18,11 @@
 package org.apache.ignite.internal.cluster.management.topology.api;
 
 import static java.util.Collections.emptySet;
-import static java.util.function.Function.identity;
 
 import java.util.Collection;
-import java.util.Map;
-import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Collectors;
+import org.apache.ignite.internal.tostring.IgniteToStringInclude;
 import org.apache.ignite.internal.tostring.S;
 import org.jetbrains.annotations.TestOnly;
 
@@ -44,18 +41,16 @@ public class LogicalTopologySnapshot {
 
     private final long version;
 
-    private final Map<String, LogicalNode> nodesByName;
-    private final Map<UUID, LogicalNode> nodesById;
+    @IgniteToStringInclude
+    private final Set<LogicalNode> nodes;
 
     private final UUID clusterId;
 
     /** Constructor. */
     public LogicalTopologySnapshot(long version, Collection<LogicalNode> 
nodes, UUID clusterId) {
         this.version = version;
+        this.nodes = Set.copyOf(nodes);
         this.clusterId = clusterId;
-
-        this.nodesByName = 
nodes.stream().collect(Collectors.toUnmodifiableMap(LogicalNode::name, 
identity()));
-        this.nodesById = 
nodes.stream().collect(Collectors.toUnmodifiableMap(LogicalNode::id, 
identity()));
     }
 
     /**
@@ -76,76 +71,8 @@ public class LogicalTopologySnapshot {
     /**
      * Returns the nodes that comprise the logical topology.
      */
-    public Collection<LogicalNode> nodes() {
-        return nodesById.values();
-    }
-
-    /**
-     * Returns the mapping of node names to the nodes that comprise the 
logical topology.
-     */
-    public Map<String, LogicalNode> nodesByName() {
-        return nodesByName;
-    }
-
-    /**
-     * Returns the mapping of node identifiers to the nodes that comprise the 
logical topology.
-     */
-    public Map<UUID, LogicalNode> nodesById() {
-        return nodesById;
-    }
-
-    /**
-     * Returns the node names that comprise the logical topology.
-     */
-    public Set<String> nodeNames() {
-        return nodesByName.keySet();
-    }
-
-    /**
-     * Returns the node identifiers that comprise the logical topology.
-     */
-    public Set<UUID> nodeIds() {
-        return nodesById.keySet();
-    }
-
-    /**
-     * Returns {@code true} if this topology snapshot contains a node with the 
given {@code id}, and {@code false} otherwise.
-     *
-     * @param nodeId Node id.
-     * @return {@code true} if this topology snapshot contains a node with the 
given {@code id}, and {@code false} otherwise.
-     */
-    public boolean hasNode(UUID nodeId) {
-        return nodesById.containsKey(nodeId);
-    }
-
-    /**
-     * Returns {@code true} if this topology snapshot contains a node with the 
given {@code nodeName}, and {@code false} otherwise.
-     *
-     * @param nodeName Node name, aka consistent id.
-     * @return {@code true} if this topology snapshot contains a node with the 
given {@code nodeName}, and {@code false} otherwise.
-     */
-    public boolean hasNode(String nodeName) {
-        return nodesByName.containsKey(nodeName);
-    }
-
-    /**
-     * Returns a node with the given {@code nodeId} in this topology snapshot.
-     *
-     * @param nodeId Node id to find.
-     * @return Node with the given {@code nodeId} in this topology snapshot.
-     */
-    public Optional<LogicalNode> node(UUID nodeId) {
-        return Optional.ofNullable(nodesById.get(nodeId));
-    }
-
-    /**
-     * Returns a node with the given {@code nodeId} in this topology snapshot.
-     *
-     * @param nodeName Node name to find.
-     * @return Node with the given {@code nodeName} in this topology snapshot.
-     */
-    public Optional<LogicalNode> node(String nodeName) {
-        return Optional.ofNullable(nodesByName.get(nodeName));
+    public Set<LogicalNode> nodes() {
+        return nodes;
     }
 
     /**
@@ -155,17 +82,8 @@ public class LogicalTopologySnapshot {
         return clusterId;
     }
 
-    /**
-     * Returns the number of nodes in this snapshot.
-     *
-     * @return Number of nodes in this snapshot.
-     */
-    public int size() {
-        return nodesById.size();
-    }
-
     @Override
     public String toString() {
-        return S.toString(LogicalTopologySnapshot.class, this, "nodes", 
nodesById.values());
+        return S.toString(LogicalTopologySnapshot.class, this);
     }
 }
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
index 10bdae1031f..e281ab91983 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializer.java
@@ -39,7 +39,7 @@ public class LogicalTopologySnapshotSerializer extends 
VersionedSerializer<Logic
     protected void writeExternalData(LogicalTopologySnapshot snapshot, 
IgniteDataOutput out) throws IOException {
         out.writeVarInt(snapshot.version());
 
-        out.writeVarInt(snapshot.size());
+        out.writeVarInt(snapshot.nodes().size());
         for (LogicalNode node : snapshot.nodes()) {
             logicalNodeSerializer.writeExternal(node, out);
         }
diff --git 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
index 0d1cbed81c4..6492abe0944 100644
--- 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
+++ 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/LogicalTopologyImplTest.java
@@ -19,6 +19,7 @@ package 
org.apache.ignite.internal.cluster.management.topology;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.UUID.randomUUID;
+import static java.util.stream.Collectors.toList;
 import static 
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.contains;
@@ -216,8 +217,9 @@ class LogicalTopologyImplTest extends 
BaseIgniteAbstractTest {
 
         storage.restoreSnapshot(snapshotDir);
 
-        Set<String> namesInTopology = 
topology.getLogicalTopology().nodeNames();
-
+        List<String> namesInTopology = 
topology.getLogicalTopology().nodes().stream()
+                .map(InternalClusterNode::name)
+                .collect(toList());
         assertThat(namesInTopology, contains("node"));
     }
 
diff --git 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
index fa49e6915dd..81e88fa402e 100644
--- 
a/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
+++ 
b/modules/cluster-management/src/test/java/org/apache/ignite/internal/cluster/management/topology/api/LogicalTopologySnapshotSerializerTest.java
@@ -19,7 +19,6 @@ package 
org.apache.ignite.internal.cluster.management.topology.api;
 
 import static java.util.stream.Collectors.toList;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
@@ -45,7 +44,7 @@ class LogicalTopologySnapshotSerializerTest {
         LogicalTopologySnapshot restoredSnapshot = 
VersionedSerialization.fromBytes(bytes, serializer);
 
         assertThat(restoredSnapshot.version(), is(originalSnapshot.version()));
-        assertThat(restoredSnapshot.nodes(), 
containsInAnyOrder(originalSnapshot.nodes().toArray()));
+        assertThat(restoredSnapshot.nodes(), 
equalTo(originalSnapshot.nodes()));
         assertThat(restoredSnapshot.clusterId(), 
equalTo(originalSnapshot.clusterId()));
     }
 
diff --git 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
index a50449cadcd..79883be747f 100644
--- 
a/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
+++ 
b/modules/cluster-management/src/testFixtures/java/org/apache/ignite/internal/cluster/management/MockNode.java
@@ -28,7 +28,6 @@ import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -258,7 +257,7 @@ public class MockNode {
         return workDir;
     }
 
-    CompletableFuture<Collection<LogicalNode>> logicalTopologyNodes() {
+    CompletableFuture<Set<LogicalNode>> logicalTopologyNodes() {
         return 
clusterManager().logicalTopology().thenApply(LogicalTopologySnapshot::nodes);
     }
 
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
index 6dc5c82ec39..748490a54e2 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DefaultNodeCallback.java
@@ -26,6 +26,7 @@ import java.util.stream.Collectors;
 import org.apache.ignite.deployment.DeploymentUnit;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.deployunit.metastore.DeploymentUnitStore;
 import org.apache.ignite.internal.deployunit.metastore.NodeEventCallback;
 import 
org.apache.ignite.internal.deployunit.metastore.status.UnitClusterStatus;
@@ -90,10 +91,10 @@ public class DefaultNodeCallback extends NodeEventCallback {
     public void onRemoving(String id, Version version, List<UnitNodeStatus> 
holders) {
         cmgManager.logicalTopology()
                 .thenAccept(snapshot -> {
+                    Set<String> nodes = 
snapshot.nodes().stream().map(LogicalNode::name).collect(Collectors.toSet());
                     boolean allRemoved = holders.stream()
-                            .filter(nodeStatus -> 
snapshot.hasNode(nodeStatus.nodeId()))
+                            .filter(nodeStatus -> 
nodes.contains(nodeStatus.nodeId()))
                             .allMatch(nodeStatus -> nodeStatus.status() == 
REMOVING);
-
                     if (allRemoved) {
                         deploymentUnitStore.updateClusterStatus(id, version, 
REMOVING);
                     }
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
index d1ce6596435..6dbe43347ee 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/DeploymentManagerImpl.java
@@ -41,6 +41,7 @@ import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologyService;
 import org.apache.ignite.internal.deployunit.UnitStatuses.UnitStatusesBuilder;
 import 
org.apache.ignite.internal.deployunit.configuration.DeploymentConfiguration;
@@ -276,10 +277,13 @@ public class DeploymentManagerImpl implements 
IgniteDeployment {
                     if (success) {
                         return cmgManager.logicalTopology()
                                 .thenCompose(logicalTopology -> {
+                                    Set<String> logicalNodes = 
logicalTopology.nodes().stream()
+                                            .map(LogicalNode::name)
+                                            .collect(Collectors.toSet());
                                     // Set OBSOLETE status only to nodes which 
are present in the topology
                                     return deploymentUnitStore.getAllNodes(id, 
version)
                                             .thenCompose(nodes -> 
allOf(nodes.stream()
-                                                    
.filter(logicalTopology::hasNode)
+                                                    
.filter(logicalNodes::contains)
                                                     .map(node -> 
deploymentUnitStore.updateNodeStatus(node, id, version, OBSOLETE))
                                                     
.toArray(CompletableFuture[]::new)))
                                             .thenApply(v -> {
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
index d5cdf89306e..901477c53de 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/NodesToDeploy.java
@@ -21,18 +21,23 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
-import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.deployunit.exception.InvalidNodesArgumentException;
+import org.apache.ignite.internal.network.InternalClusterNode;
 
 /**
  * Nodes for initial deploy.
  */
 public class NodesToDeploy {
-    /** Direct nodes list. */
+    /**
+     * Direct nodes list.
+     */
     private final List<String> nodesList;
 
-    /** Deploy nodes mode. */
+    /**
+     * Deploy nodes mode.
+     */
     private final InitialDeployMode deployMode;
 
     public NodesToDeploy(List<String> nodesList) {
@@ -61,9 +66,10 @@ public class NodesToDeploy {
     private CompletableFuture<Set<String>> 
extractNodesFromMode(ClusterManagementGroupManager cmgManager) {
         switch (deployMode) {
             case ALL:
-                return cmgManager
-                        .logicalTopology()
-                        .thenApply(LogicalTopologySnapshot::nodeNames);
+                return cmgManager.logicalTopology()
+                        .thenApply(snapshot -> snapshot.nodes().stream()
+                                .map(InternalClusterNode::name)
+                                .collect(Collectors.toUnmodifiableSet()));
             case MAJORITY:
             default:
                 return cmgManager.majority();
@@ -80,11 +86,13 @@ public class NodesToDeploy {
     private CompletableFuture<Set<String>> 
extractNodesFromList(ClusterManagementGroupManager cmgManager) {
         return cmgManager.majority()
                 .thenCompose(majority -> cmgManager.logicalTopology()
-                        .thenApply(snapshot -> {
+                        .thenApply(snapshot -> snapshot.nodes().stream()
+                                .map(InternalClusterNode::name)
+                                .collect(Collectors.toUnmodifiableSet()))
+                        .thenApply(allNodes -> {
                             Set<String> result = new HashSet<>(majority);
-
                             for (String node : nodesList) {
-                                if (!snapshot.hasNode(node)) {
+                                if (!allNodes.contains(node)) {
                                     throw new InvalidNodesArgumentException(
                                             "Node \"" + node + "\" is not 
present in the logical topology"
                                     );
diff --git 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
index 5cda731cc13..7575ab21ee9 100644
--- 
a/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
+++ 
b/modules/code-deployment/src/main/java/org/apache/ignite/internal/deployunit/metastore/ClusterEventCallbackImpl.java
@@ -19,11 +19,15 @@ package org.apache.ignite.internal.deployunit.metastore;
 
 import static org.apache.ignite.internal.deployunit.DeploymentStatus.REMOVING;
 
+import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 import org.apache.ignite.deployment.version.Version;
 import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.deployunit.FileDeployerService;
 import 
org.apache.ignite.internal.deployunit.metastore.status.UnitClusterStatus;
+import org.apache.ignite.internal.deployunit.metastore.status.UnitNodeStatus;
 
 /** Listener of deployment unit cluster status changes. */
 public class ClusterEventCallbackImpl extends ClusterEventCallback {
@@ -81,10 +85,15 @@ public class ClusterEventCallbackImpl extends 
ClusterEventCallback {
 
     private void removeClusterStatus(String id, Version version, UUID opId) {
         cmgManager.logicalTopology().thenAccept(logicalTopology -> {
+            Set<String> logicalNodes = logicalTopology.nodes().stream()
+                    .map(LogicalNode::name)
+                    .collect(Collectors.toSet());
             deploymentUnitStore.getAllNodeStatuses(id, 
version).thenAccept(statuses -> {
                 boolean emptyTopology = statuses.stream()
-                        .noneMatch(unitNodeStatus -> 
logicalTopology.hasNode(unitNodeStatus.nodeId()));
-
+                        .map(UnitNodeStatus::nodeId)
+                        .filter(logicalNodes::contains)
+                        .findAny()
+                        .isEmpty();
                 if (emptyTopology) {
                     deploymentUnitStore.removeClusterStatus(id, version, opId);
                 }
diff --git 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
index b464c14ba75..ee1a89ae81a 100644
--- 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
+++ 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/distributionzones/ItDataNodesManagerTest.java
@@ -63,7 +63,7 @@ class ItDataNodesManagerTest extends 
ClusterPerTestIntegrationTest {
         LogicalTopologyService logicalTopologyService = 
node.logicalTopologyService();
 
         Awaitility.waitAtMost(2, TimeUnit.SECONDS)
-                .untilAsserted(() -> assertEquals(2, 
logicalTopologyService.localLogicalTopology().size()));
+                .untilAsserted(() -> assertEquals(2, 
logicalTopologyService.localLogicalTopology().nodes().size()));
 
         waitForDataNodes(node, ZONE_NAME, Set.of(node.name()));
 
diff --git 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
index bebc9a4407c..c9907b58303 100644
--- 
a/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
+++ 
b/modules/distribution-zones/src/integrationTest/java/org/apache/ignite/internal/rebalance/ItRebalanceDistributedTest.java
@@ -385,7 +385,7 @@ public class ItRebalanceDistributedTest extends 
BaseIgniteAbstractTest {
 
                     assertThat(logicalTopologyFuture, 
willCompleteSuccessfully());
 
-                    return logicalTopologyFuture.join().size() == NODE_COUNT;
+                    return logicalTopologyFuture.join().nodes().size() == 
NODE_COUNT;
                 },
                 AWAIT_TIMEOUT_MILLIS
         ));
diff --git 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
index 0ddce418aee..4c92a01031b 100644
--- 
a/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
+++ 
b/modules/distribution-zones/src/main/java/org/apache/ignite/internal/distributionzones/DistributionZoneManager.java
@@ -521,7 +521,7 @@ public class DistributionZoneManager extends
         }
 
         try {
-            Collection<LogicalNode> logicalTopology = newTopology.nodes();
+            Set<LogicalNode> logicalTopology = newTopology.nodes();
 
             Condition condition;
             Update update;
diff --git 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
index ba60fc971dd..ec4bfc0a85c 100644
--- 
a/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
+++ 
b/modules/metastorage/src/integrationTest/java/org/apache/ignite/internal/metastorage/impl/ItMetaStorageMultipleNodesVsStorageTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.metastorage.impl;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.concurrent.CompletableFuture.allOf;
+import static java.util.stream.Collectors.toSet;
 import static 
org.apache.ignite.internal.metastorage.TestMetasStorageUtils.checkEntry;
 import static org.apache.ignite.internal.metastorage.dsl.Conditions.notExists;
 import static org.apache.ignite.internal.metastorage.dsl.Conditions.revision;
@@ -42,7 +43,6 @@ import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
-import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import 
org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
 import org.apache.ignite.internal.hlc.HybridTimestamp;
 import org.apache.ignite.internal.lang.ByteArray;
@@ -53,6 +53,7 @@ import 
org.apache.ignite.internal.metastorage.server.KeyValueStorage;
 import 
org.apache.ignite.internal.metastorage.server.ReadOperationForCompactionTracker;
 import org.apache.ignite.internal.metastorage.server.time.ClusterTime;
 import org.apache.ignite.internal.metastorage.server.time.ClusterTimeImpl;
+import org.apache.ignite.internal.network.InternalClusterNode;
 import org.apache.ignite.internal.raft.Peer;
 import org.apache.ignite.internal.raft.service.RaftGroupService;
 import org.junit.jupiter.api.Test;
@@ -175,7 +176,7 @@ abstract class ItMetaStorageMultipleNodesVsStorageTest 
extends ItMetaStorageMult
 
         CompletableFuture<Set<String>> logicalTopologyNodes = 
firstNode.cmgManager
                 .logicalTopology()
-                .thenApply(LogicalTopologySnapshot::nodeNames);
+                .thenApply(logicalTopology -> 
logicalTopology.nodes().stream().map(InternalClusterNode::name).collect(toSet()));
 
         assertThat(logicalTopologyNodes, willBe(Set.of(firstNode.name(), 
secondNode.name())));
 
diff --git 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
index 0a91aa67eb7..1bb5a4d3744 100644
--- 
a/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
+++ 
b/modules/partition-replicator/src/integrationTest/java/org/apache/ignite/internal/partition/replicator/ItAbstractColocationTest.java
@@ -187,7 +187,7 @@ abstract class ItAbstractColocationTest extends 
IgniteAbstractTest {
 
                     assertThat(logicalTopologyFuture, 
willCompleteSuccessfully());
 
-                    return logicalTopologyFuture.join().size() == 
cluster.size();
+                    return logicalTopologyFuture.join().nodes().size() == 
cluster.size();
                 },
                 AWAIT_TIMEOUT_MILLIS
         ));
diff --git 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
index aae6504cf5f..1c1f9dd7a3e 100644
--- 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
+++ 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/TopologyTracker.java
@@ -25,6 +25,7 @@ import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopolog
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.network.InternalClusterNode;
+import org.apache.ignite.internal.util.CollectionUtils;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -92,11 +93,17 @@ public class TopologyTracker {
     public @Nullable InternalClusterNode nodeByConsistentId(String 
consistentId) {
         LogicalTopologySnapshot logicalTopologySnap0 = topologySnapRef.get();
 
-        if (logicalTopologySnap0 == null || logicalTopologySnap0.size() == 0) {
+        if (logicalTopologySnap0 == null || 
CollectionUtils.nullOrEmpty(logicalTopologySnap0.nodes())) {
             return null;
         }
 
-        return logicalTopologySnap0.node(consistentId).orElse(null);
+        for (LogicalNode node : logicalTopologySnap0.nodes()) {
+            if (node.name().equals(consistentId)) {
+                return node;
+            }
+        }
+
+        return null;
     }
 
     LogicalTopologySnapshot currentTopologySnapshot() {
diff --git 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
index 8ec050f6044..83535b47a79 100644
--- 
a/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
+++ 
b/modules/placement-driver/src/main/java/org/apache/ignite/internal/placementdriver/negotiation/LeaseAgreement.java
@@ -18,11 +18,14 @@
 package org.apache.ignite.internal.placementdriver.negotiation;
 
 import static java.util.Objects.requireNonNull;
+import static java.util.stream.Collectors.toSet;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 import static org.apache.ignite.internal.util.IgniteUtils.findAny;
 
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import 
org.apache.ignite.internal.cluster.management.topology.api.LogicalTopologySnapshot;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
@@ -188,7 +191,9 @@ public class LeaseAgreement {
 
             responseFut.complete(null);
         } else if (currentTopologySnapshot != null) {
-            if (lease.getLeaseholderId() == null || 
!currentTopologySnapshot.hasNode(lease.getLeaseholderId())) {
+            Set<UUID> nodeIds = 
currentTopologySnapshot.nodes().stream().map(LogicalNode::id).collect(toSet());
+
+            if (!nodeIds.contains(lease.getLeaseholderId())) {
                 LOG.info("Lease was not negotiated because the node has left 
the logical topology [node={}, nodeId={}, group={}]",
                         lease.getLeaseholder(), lease.getLeaseholderId(), 
groupId);
 
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
index ef6af19929f..147d111c33f 100644
--- 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/cluster/ItDataNodesControllerTest.java
@@ -244,7 +244,7 @@ public class ItDataNodesControllerTest extends 
ClusterPerTestIntegrationTest {
         LogicalTopologyService logicalTopologyService = 
node.logicalTopologyService();
 
         Awaitility.waitAtMost(1, TimeUnit.SECONDS).untilAsserted(() ->
-                assertEquals(expectedTopologySize, 
logicalTopologyService.localLogicalTopology().size())
+                assertEquals(expectedTopologySize, 
logicalTopologyService.localLogicalTopology().nodes().size())
         );
     }
 
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
index f602726acb6..765c25f61ac 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/ItIgniteNodeRestartTest.java
@@ -106,6 +106,7 @@ import 
org.apache.ignite.internal.cluster.management.configuration.NodeAttribute
 import 
org.apache.ignite.internal.cluster.management.raft.RocksDbClusterStateStorage;
 import 
org.apache.ignite.internal.cluster.management.topology.LogicalTopologyImpl;
 import 
org.apache.ignite.internal.cluster.management.topology.LogicalTopologyServiceImpl;
+import org.apache.ignite.internal.cluster.management.topology.api.LogicalNode;
 import org.apache.ignite.internal.components.LogSyncer;
 import org.apache.ignite.internal.configuration.ComponentWorkingDir;
 import org.apache.ignite.internal.configuration.ConfigurationModules;
@@ -1115,16 +1116,17 @@ public class ItIgniteNodeRestartTest extends 
BaseIgniteRestartTest {
         List<IgniteImpl> nodes = startNodes(3);
 
         // Here we check that node sees itself in local logical topology.
-        nodes.forEach(node -> 
assertTrue(node.logicalTopologyService().localLogicalTopology().hasNode(node.id())));
+        nodes.forEach(node -> 
assertTrue(node.logicalTopologyService().localLogicalTopology().nodes().stream().map(LogicalNode::id)
+                .collect(toSet()).contains(node.id())));
 
         // Actually we have stronger guarantees because of awaiting all nodes 
to start inside startNodes.
         // On one node (cmg leader) we will see all three nodes in local 
logical topology.
         // On the node that started second we will see at least two nodes.
         // On the third node we will see all three nodes.
         // All in all that means that in total we will see at least (3 + 2 + 
3) nodes.
-        int sumOfLogicalTopologyProjectionSizes = nodes.stream()
-                .mapToInt(node -> 
node.logicalTopologyService().localLogicalTopology().size())
-                .sum();
+        Integer sumOfLogicalTopologyProjectionSizes =
+                nodes.stream().map(node -> 
node.logicalTopologyService().localLogicalTopology().nodes().size())
+                        .reduce(0, Integer::sum);
 
         assertTrue(sumOfLogicalTopologyProjectionSizes >= 3 + 2 + 3);
     }
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index ec77e546c2d..39de9eee97b 100644
--- 
a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ 
b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.app;
 
 import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.stream.Collectors.toSet;
 import static org.apache.ignite.internal.configuration.IgnitePaths.cmgPath;
 import static 
org.apache.ignite.internal.configuration.IgnitePaths.metastoragePath;
 import static 
org.apache.ignite.internal.configuration.IgnitePaths.partitionsPath;
@@ -1734,7 +1735,7 @@ public class IgniteImpl implements Ignite {
             CompletableFuture<Void> awaitSelfInLogicalTopologyFuture,
             LogicalTopologyEventListener awaitSelfListener
     ) {
-        if (logicalTopologySnapshot.hasNode(id())) {
+        if 
(logicalTopologySnapshot.nodes().stream().map(LogicalNode::id).collect(toSet()).contains(id()))
 {
             awaitSelfInLogicalTopologyFuture.complete(null);
             logicalTopologyService.removeEventListener(awaitSelfListener);
         }
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
index 56eb6282163..04d14234df5 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlCreateZoneTest.java
@@ -98,7 +98,7 @@ class ItSqlCreateZoneTest extends 
ClusterPerTestIntegrationTest {
         IgniteImpl node1 = unwrapIgniteImpl(cluster.startNode(1));
 
         assertTrue(waitForCondition(
-                () -> 
node1.logicalTopologyService().localLogicalTopology().size() == 2,
+                () -> 
node1.logicalTopologyService().localLogicalTopology().nodes().size() == 2,
                 10_000
         ));
 
@@ -120,17 +120,17 @@ class ItSqlCreateZoneTest extends 
ClusterPerTestIntegrationTest {
 
         // Check that Node 0 and 2 will see all three nodes in local logical 
topologies.
         assertTrue(waitForCondition(
-                () -> 
unwrapIgniteImpl(node(0)).logicalTopologyService().localLogicalTopology().size()
 == 3,
+                () -> 
unwrapIgniteImpl(node(0)).logicalTopologyService().localLogicalTopology().nodes().size()
 == 3,
                 10_000
         ));
 
         assertTrue(waitForCondition(
-                () -> 
unwrapIgniteImpl(node(2)).logicalTopologyService().localLogicalTopology().size()
 == 3,
+                () -> 
unwrapIgniteImpl(node(2)).logicalTopologyService().localLogicalTopology().nodes().size()
 == 3,
                 10_000
         ));
 
         // And we expect that node 1 won't see node 2 in its local logical 
topology.
-        assertEquals(2, 
node1.logicalTopologyService().localLogicalTopology().size());
+        assertEquals(2, 
node1.logicalTopologyService().localLogicalTopology().nodes().size());
 
         // But still we're able to create zone with extra profile on node 2 
because node 1 will try to ask CMG leader (node 0) directly over
         // the network for its up-to-date leader's local logical topology and 
check this snapshot's storage profiles that should
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
index f8b8e97f6d1..6d1c5645fd1 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/mapping/MappingServiceImpl.java
@@ -518,7 +518,7 @@ public class MappingServiceImpl implements MappingService, 
LogicalTopologyEventL
         void update(LogicalTopologySnapshot topologySnapshot) {
             synchronized (this) {
                 if (topology.version() < topologySnapshot.version()) {
-                    topology = new 
TopologySnapshot(topologySnapshot.version(), topologySnapshot.nodeNames());
+                    topology = new 
TopologySnapshot(topologySnapshot.version(), deriveNodeNames(topologySnapshot));
                 }
 
                 if (initialTopologyFuture.isDone() || 
!topology.nodes().contains(localNodeName)) {
@@ -533,6 +533,12 @@ public class MappingServiceImpl implements MappingService, 
LogicalTopologyEventL
             return topology;
         }
 
+        private Set<String> deriveNodeNames(LogicalTopologySnapshot topology) {
+            return topology.nodes().stream()
+                    .map(LogicalNode::name)
+                    .collect(Collectors.toUnmodifiableSet());
+        }
+
         class TopologySnapshot {
             private final Set<String> nodes;
             private final long version;
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
index 2c4e3b24599..221615a8801 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/ClusterWideStorageProfileValidator.java
@@ -104,7 +104,7 @@ public class ClusterWideStorageProfileValidator implements 
StorageProfileValidat
     }
 
     private static Set<String> 
extractStorageProfileNamesFromLogicalTopologySnapshot(LogicalTopologySnapshot 
snapshot) {
-        Collection<LogicalNode> logicalNodes = snapshot.nodes();
+        Set<LogicalNode> logicalNodes = snapshot.nodes();
 
         // Assume default persistent + rocks + aimem profiles on each node in 
average.
         Set<String> topologyWideProfiles = new HashSet<>(logicalNodes.size() * 
3);
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
index 8693e257d27..8a79b01d84c 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/statistic/StatisticAggregatorImpl.java
@@ -29,6 +29,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -54,7 +55,7 @@ public class StatisticAggregatorImpl implements
         StatisticAggregator<Collection<InternalTable>, 
CompletableFuture<Int2ObjectMap<PartitionModificationInfo>>> {
     private static final IgniteLogger LOG = 
Loggers.forClass(StatisticAggregatorImpl.class);
 
-    private final Supplier<Collection<LogicalNode>> clusterNodes;
+    private final Supplier<Set<LogicalNode>> clusterNodes;
 
     private final MessagingService messagingService;
 
@@ -67,7 +68,7 @@ public class StatisticAggregatorImpl implements
 
     /** Constructor. */
     public StatisticAggregatorImpl(
-            Supplier<Collection<LogicalNode>> clusterNodes,
+            Supplier<Set<LogicalNode>> clusterNodes,
             MessagingService messagingService
     ) {
         this.clusterNodes = clusterNodes;
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
index 3db3d33b4f4..d989ce29c7c 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/framework/ClusterServiceFactory.java
@@ -148,7 +148,10 @@ public class ClusterServiceFactory {
         }
 
         private static @Nullable InternalClusterNode 
findNodeByName(LogicalTopology logicalTopology, String name) {
-            return 
logicalTopology.getLogicalTopology().node(name).orElse(null);
+            return logicalTopology.getLogicalTopology().nodes().stream()
+                    .filter(node -> node.name().equals(name))
+                    .findFirst()
+                    .orElse(null);
         }
 
         @Override
@@ -192,7 +195,10 @@ public class ClusterServiceFactory {
 
         @Override
         public @Nullable InternalClusterNode getById(UUID id) {
-            return logicalTopology.getLogicalTopology().node(id).orElse(null);
+            return logicalTopology.getLogicalTopology().nodes().stream()
+                    .filter(node -> node.id().equals(id))
+                    .findFirst()
+                    .orElse(null);
         }
 
         @Override
diff --git 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
index c2dd9a90e43..87f6029a643 100644
--- 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
+++ 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItCmgDisasterRecoveryTest.java
@@ -124,7 +124,8 @@ class ItCmgDisasterRecoveryTest extends 
ItSystemGroupDisasterRecoveryTest {
         IgniteImpl node2 = unwrapIgniteImpl(cluster.startNode(2));
 
         assertTrue(waitForCondition(
-                () -> 
node2.logicalTopologyService().localLogicalTopology().hasNode(node2.name()),
+                () -> 
node2.logicalTopologyService().localLogicalTopology().nodes().stream()
+                        .anyMatch(n -> node2.name().equals(n.name())),
                 SECONDS.toMillis(10)
         ));
     }
diff --git 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
index a9e14d215c4..ed5ed9368c2 100644
--- 
a/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
+++ 
b/modules/system-disaster-recovery/src/integrationTest/java/org/apache/ignite/internal/disaster/system/ItSystemGroupDisasterRecoveryTest.java
@@ -138,6 +138,6 @@ abstract class ItSystemGroupDisasterRecoveryTest extends 
ClusterPerTestIntegrati
     }
 
     final void assertTopologyContainsNode(int nodeIndex, 
LogicalTopologySnapshot topologySnapshot) {
-        assertTrue(topologySnapshot.hasNode(cluster.nodeName(nodeIndex)));
+        assertTrue(topologySnapshot.nodes().stream().anyMatch(node -> 
node.name().equals(cluster.nodeName(nodeIndex))));
     }
 }
diff --git 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
index 37285d0049a..7af3be4746a 100644
--- 
a/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
+++ 
b/modules/table/src/integrationTest/java/org/apache/ignite/internal/table/distributed/disaster/ItHighAvailablePartitionsRecoveryByFilterUpdateTest.java
@@ -556,7 +556,10 @@ public class 
ItHighAvailablePartitionsRecoveryByFilterUpdateTest extends Abstrac
     }
 
     private static LogicalNode getLogicalNode(IgniteImpl ignite) {
-        return 
ignite.logicalTopologyService().localLogicalTopology().node(ignite.name())
+
+        return 
ignite.logicalTopologyService().localLogicalTopology().nodes().stream()
+                .filter(n -> n.name().equals(ignite.name()))
+                .findFirst()
                 .orElseThrow(() -> new IllegalStateException("Node not found 
in logical topology: " + ignite.name()));
     }
 }

Reply via email to