Repository: skiptests/astraea
Pull request #452 (2022-07-03 15:49:53)

tweak ClusterInfo#of(ClusterInfo, Beans)
一點點的重構，以及讓介面更彈性


Patch:
diff --git a/app/src/main/java/org/astraea/app/cost/ClusterInfo.java b/app/src/main/java/org/astraea/app/cost/ClusterInfo.java
index 8aa822c3..d1dd42c2 100644
--- a/app/src/main/java/org/astraea/app/cost/ClusterInfo.java
+++ b/app/src/main/java/org/astraea/app/cost/ClusterInfo.java
@@ -16,15 +16,13 @@
  */
 package org.astraea.app.cost;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.astraea.app.admin.ClusterBean;
 import org.astraea.app.metrics.HasBeanObject;
 
@@ -98,52 +96,60 @@ public interface ClusterInfo {
   /**
    * merge the beans into cluster information
    *
-   * @param cluster cluster information
+   * @param clusterInfo cluster information
    * @param beans extra beans
    * @return a new cluster information with extra beans
    */
-  static ClusterInfo of(ClusterInfo cluster, Map<Integer, Collection<HasBeanObject>> beans) {
-    var all = new HashMap<Integer, List<HasBeanObject>>();
-    cluster
-        .clusterBean()
-        .all()
-        .forEach((key, value) -> all.computeIfAbsent(key, k -> new ArrayList<>()).addAll(value));
-    beans.forEach((key, value) -> all.computeIfAbsent(key, k -> new ArrayList<>()).addAll(value));
+  static ClusterInfo of(
+      ClusterInfo clusterInfo, Map<Integer, ? extends Collection<HasBeanObject>> beans) {
+    var clusterBean =
+        ClusterBean.of(
+            Stream.concat(
+                    clusterInfo.clusterBean().all().entrySet().stream(), beans.entrySet().stream())
+                .collect(
+                    Collectors.toMap(
+                        Map.Entry::getKey,
+                        Map.Entry::getValue,
+                        // Normally, the cluster info used to merge with beans has no beans. Hence,
+                        // the cost of merge is acceptable
+                        (l, r) ->
+                            Stream.concat(l.stream(), r.stream())
+                                .collect(Collectors.toUnmodifiableList()))));
     return new ClusterInfo() {
 
       @Override
       public List<NodeInfo> nodes() {
-        return cluster.nodes();
+        return clusterInfo.nodes();
       }
 
       @Override
       public Set<String> dataDirectories(int brokerId) {
-        return cluster.dataDirectories(brokerId);
+        return clusterInfo.dataDirectories(brokerId);
       }
 
       @Override
       public List<ReplicaInfo> availableReplicaLeaders(String topic) {
-        return cluster.availableReplicaLeaders(topic);
+        return clusterInfo.availableReplicaLeaders(topic);
       }
 
       @Override
       public List<ReplicaInfo> availableReplicas(String topic) {
-        return cluster.availableReplicas(topic);
+        return clusterInfo.availableReplicas(topic);
       }
 
       @Override
       public Set<String> topics() {
-        return cluster.topics();
+        return clusterInfo.topics();
       }
 
       @Override
       public List<ReplicaInfo> replicas(String topic) {
-        return cluster.replicas(topic);
+        return clusterInfo.replicas(topic);
       }
 
       @Override
       public ClusterBean clusterBean() {
-        return ClusterBean.of(Collections.unmodifiableMap(all));
+        return clusterBean;
       }
     };
   }


Test patch:
diff --git a/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java b/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
index 741c6139..e49cc681 100644
--- a/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
+++ b/app/src/test/java/org/astraea/app/cost/ClusterInfoTest.java
@@ -17,8 +17,11 @@
 package org.astraea.app.cost;
 
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import org.apache.kafka.common.Cluster;
+import org.astraea.app.admin.ClusterBean;
+import org.astraea.app.metrics.HasBeanObject;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
@@ -65,4 +68,17 @@ public class ClusterInfoTest {
     Assertions.assertThrows(
         UnsupportedOperationException.class, () -> clusterInfo.dataDirectories(0));
   }
+
+  @Test
+  void testMergeWithBeans() {
+    var bean0 = Mockito.mock(HasBeanObject.class);
+    var bean1 = Mockito.mock(HasBeanObject.class);
+    var clusterBean = ClusterBean.of(Map.of(10, List.of(bean0)));
+    var mergedBeans = Map.of(10, List.of(bean1));
+    var origin = Mockito.mock(ClusterInfo.class);
+    Mockito.when(origin.clusterBean()).thenReturn(clusterBean);
+    var newClusterInfo = ClusterInfo.of(origin, mergedBeans);
+    Assertions.assertEquals(1, newClusterInfo.clusterBean().all().size());
+    Assertions.assertEquals(2, newClusterInfo.clusterBean().all().get(10).size());
+  }
 }