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

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new c47706be5 fix(client): sort aggregated connection rows (#5773)
c47706be5 is described below

commit c47706be519f4b21d37511c3dfd7c5c32df08d1b
Author: 0 <[email protected]>
AuthorDate: Mon Oct 19 18:40:00 2026 +0800

    fix(client): sort aggregated connection rows (#5773)
    
    Verified against `rocketmq-studio` at b88aedc34 before merging: 
缺陷仍在(`provider/apache/RocketMQClientProvider.java:87-96` 私有 funnel 仍是两个 
`addAll` 后直接 `return connections`,无排序;`Comparator` 已在 `:51` import;`ClientType
    
    merge-tree clean against the current trunk. Merged as-is (squash) per the 
maintainer review of 2026-10-19.
    
    Scope note: this only orders the cluster-scoped client list; the 
producer/topic-scoped scan entries keep their existing order.
---
 .../provider/apache/RocketMQClientProvider.java    | 11 ++++++++++
 .../apache/RocketMQClientProviderTest.java         | 24 ++++++++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProvider.java
 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProvider.java
index cd9e9a6ed..9b9c68b9e 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProvider.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProvider.java
@@ -93,6 +93,17 @@ public class RocketMQClientProvider implements 
ClientProvider {
         if (clientType == null || clientType == ClientType.Consumer) {
             connections.addAll(findConsumerConnections(adminExt, clusterId));
         }
+        // The rows are aggregated by walking the broker/proxy tables, whose 
iteration order is
+        // hash-based and changes between snapshots; sort by a stable key so 
the client list
+        // does not reshuffle between two views of the same cluster.
+        connections.sort(Comparator
+                .comparing(ClientConnectionVO::getType, 
Comparator.nullsLast(Comparator.naturalOrder()))
+                .thenComparing(ClientConnectionVO::getGroupOrTopic,
+                        Comparator.nullsLast(Comparator.naturalOrder()))
+                .thenComparing(ClientConnectionVO::getClientId,
+                        Comparator.nullsLast(Comparator.naturalOrder()))
+                .thenComparing(ClientConnectionVO::getAddress,
+                        Comparator.nullsLast(Comparator.naturalOrder())));
         return connections;
     }
 
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProviderTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProviderTest.java
index 5464bbce6..7bd2a005c 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProviderTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQClientProviderTest.java
@@ -52,6 +52,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -422,6 +423,29 @@ class RocketMQClientProviderTest {
         verify(adminExt, never()).examineProducerConnectionInfo(anyString(), 
anyString());
     }
 
+    @Test
+    void connectionScanShouldReturnStableOrderAcrossTopologyChanges() throws 
Exception {
+        // The broker table of a route is a hash map, so its iteration order 
varies between
+        // snapshots; the aggregated client list must not inherit that 
instability.
+        ClusterInfo clusterInfo = new ClusterInfo();
+        Map<String, BrokerData> brokerAddrTable = new LinkedHashMap<>();
+        brokerAddrTable.put("broker-z", new BrokerData(
+                "cluster-a", "broker-z", new HashMap<>(Map.of(0L, 
"10.0.0.2:10911"))));
+        brokerAddrTable.put("broker-a", new BrokerData(
+                "cluster-a", "broker-a", new HashMap<>(Map.of(0L, 
"10.0.0.1:10911"))));
+        clusterInfo.setBrokerAddrTable(brokerAddrTable);
+        when(adminExt.examineBrokerClusterInfo()).thenReturn(clusterInfo);
+        when(adminExt.getAllProducerInfo("10.0.0.2:10911")).thenReturn(new 
ProducerTableInfo(Map.of(
+                "pg-zeta", List.of(producerInfo("producer-zeta", 
"10.0.0.2:1000")))));
+        when(adminExt.getAllProducerInfo("10.0.0.1:10911")).thenReturn(new 
ProducerTableInfo(Map.of(
+                "pg-alpha", List.of(producerInfo("producer-alpha", 
"10.0.0.1:1000")))));
+
+        List<ClientConnectionVO> connections = 
provider.findConnectionsAt("10.0.1.31:9876", null, "Producer");
+
+        assertThat(connections).extracting(ClientConnectionVO::getGroupOrTopic)
+                .containsExactly("pg-alpha", "pg-zeta");
+    }
+
     @Test
     void producerScanAggregatesAndDeduplicatesBrokerProducerTables() throws 
Exception {
         when(adminExt.examineBrokerClusterInfo()).thenReturn(clusterInfo(

Reply via email to