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 3b9e35fe4 fix(cloud): map vendor subscription consistency flags to the 
studio vocabulary (#4884)
3b9e35fe4 is described below

commit 3b9e35fe42125dc099f1fba04b9451c6a42421e7
Author: Wang1rrr <[email protected]>
AuthorDate: Thu Sep 24 10:45:24 2026 +0800

    fix(cloud): map vendor subscription consistency flags to the studio 
vocabulary (#4884)
    
    The subscription table's consistency status is a small fixed vocabulary: 
the Apache provider reports `consistent` when a client of the group is 
connected and leaves it null otherwise, and the console's group diagnostics 
only recognise `consistent` / `inconsistent`. The Aliyun boolean and the 
Tencent consistency code were leaked into the API response as true/false/0/1, 
which no consumer understood. A shared `SubscriptionConsistency` helper now 
translates both vendors into that vocabulary.
---
 .../common/util/SubscriptionConsistency.java       | 68 ++++++++++++++++++++++
 .../studio/provider/alibaba/AliyunConverters.java  |  3 +-
 .../provider/tencent/TencentInstanceProvider.java  |  3 +-
 .../common/util/SubscriptionConsistencyTest.java   | 44 ++++++++++++++
 .../provider/alibaba/AliyunConvertersTest.java     | 19 ++++++
 .../tencent/TencentInstanceProviderTest.java       | 23 ++++++++
 6 files changed, 158 insertions(+), 2 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistency.java
 
b/server/src/main/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistency.java
new file mode 100644
index 000000000..9e9077cc5
--- /dev/null
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistency.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package org.apache.rocketmq.studio.common.util;
+
+/**
+ * Maps a vendor subscription consistency flag to the studio {@code 
consistency} value.
+ * The Apache provider reports {@code consistent} when a client of the group 
is connected and
+ * leaves the status unknown (null) otherwise, and that is the only vocabulary 
the console
+ * understands: the subscription table colours the cell and the "inconsistent 
only" filter
+ * match {@code consistent} / {@code inconsistent}. The cloud providers 
therefore have to
+ * translate their own flags instead of leaking {@code true} / {@code false} 
or {@code 0} /
+ * {@code 1} into the API response.
+ */
+public final class SubscriptionConsistency {
+
+    /** Every client of the consumer group subscribes the same way. */
+    public static final String CONSISTENT = "consistent";
+
+    /** At least one client of the consumer group subscribes differently from 
the others. */
+    public static final String INCONSISTENT = "inconsistent";
+
+    private SubscriptionConsistency() {
+    }
+
+    /**
+     * Aliyun {@code ListConsumerGroupSubscriptions} returns the consistency 
as a boolean, where
+     * {@code true} means the subscription relationship is consistent. A 
missing value stays
+     * unknown instead of being reported as inconsistent.
+     */
+    public static String fromBoolean(Boolean consistency) {
+        if (consistency == null) {
+            return null;
+        }
+        return consistency ? CONSISTENT : INCONSISTENT;
+    }
+
+    /**
+     * Tencent {@code DescribeTopicListByGroup} returns the consistency as a 
code, where {@code 0}
+     * means consistent and {@code 1} means inconsistent. A missing or 
undocumented code stays
+     * unknown instead of being guessed.
+     */
+    public static String fromCode(Long consistency) {
+        if (consistency == null) {
+            return null;
+        }
+        if (consistency.longValue() == 0L) {
+            return CONSISTENT;
+        }
+        if (consistency.longValue() == 1L) {
+            return INCONSISTENT;
+        }
+        return null;
+    }
+}
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConverters.java
 
b/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConverters.java
index f658e48ce..f488cd8cf 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConverters.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConverters.java
@@ -32,6 +32,7 @@ import 
org.apache.rocketmq.studio.common.domain.enums.DeliveryStatus;
 import org.apache.rocketmq.studio.common.domain.enums.SubscriptionMode;
 import org.apache.rocketmq.studio.common.domain.enums.TopicPerm;
 import org.apache.rocketmq.studio.common.domain.enums.TopicType;
+import org.apache.rocketmq.studio.common.util.SubscriptionConsistency;
 import org.apache.rocketmq.studio.common.util.SubscriptionFilterModes;
 import org.apache.rocketmq.studio.instance.group.ConsumerGroupVO;
 import org.apache.rocketmq.studio.instance.group.QueueProgressVO;
@@ -220,7 +221,7 @@ final class AliyunConverters {
                 .expression(data.getFilterExpression())
                 .type(data.getFilterExpressionType())
                 
.filterMode(SubscriptionFilterModes.fromExpressionType(data.getFilterExpressionType()))
-                .consistency(data.getConsistency() == null ? null : 
String.valueOf(data.getConsistency()))
+                
.consistency(SubscriptionConsistency.fromBoolean(data.getConsistency()))
                 .build();
     }
 
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProvider.java
 
b/server/src/main/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProvider.java
index ee08031e8..95f2990aa 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProvider.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProvider.java
@@ -55,6 +55,7 @@ import 
org.apache.rocketmq.studio.common.domain.enums.TopicPerm;
 import org.apache.rocketmq.studio.common.domain.enums.TopicType;
 import org.apache.rocketmq.studio.common.exception.BusinessException;
 import org.apache.rocketmq.studio.common.util.Pagination;
+import org.apache.rocketmq.studio.common.util.SubscriptionConsistency;
 import org.apache.rocketmq.studio.instance.InstanceRepository;
 import org.apache.rocketmq.studio.instance.InstanceVO;
 import org.apache.rocketmq.studio.instance.group.ConsumerGroupVO;
@@ -1033,7 +1034,7 @@ public class TencentInstanceProvider implements 
InstanceProvider {
                 .expression(subscription.getSubString())
                 .type(subscription.getExpressionType())
                 .filterMode(subscription.getExpressionType())
-                .consistency(subscription.getConsistency() == null ? null : 
String.valueOf(subscription.getConsistency()))
+                
.consistency(SubscriptionConsistency.fromCode(subscription.getConsistency()))
                 .build();
     }
 
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistencyTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistencyTest.java
new file mode 100644
index 000000000..95bcef05b
--- /dev/null
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/common/util/SubscriptionConsistencyTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package org.apache.rocketmq.studio.common.util;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class SubscriptionConsistencyTest {
+
+    @Test
+    void mapsTheAliyunBooleanFlagTest() {
+        
assertThat(SubscriptionConsistency.fromBoolean(Boolean.TRUE)).isEqualTo("consistent");
+        
assertThat(SubscriptionConsistency.fromBoolean(Boolean.FALSE)).isEqualTo("inconsistent");
+        assertThat(SubscriptionConsistency.fromBoolean(null)).isNull();
+    }
+
+    @Test
+    void mapsTheTencentConsistencyCodeTest() {
+        
assertThat(SubscriptionConsistency.fromCode(0L)).isEqualTo("consistent");
+        
assertThat(SubscriptionConsistency.fromCode(1L)).isEqualTo("inconsistent");
+        assertThat(SubscriptionConsistency.fromCode(null)).isNull();
+    }
+
+    @Test
+    void keepsUndocumentedTencentCodesUnknownTest() {
+        assertThat(SubscriptionConsistency.fromCode(2L)).isNull();
+        assertThat(SubscriptionConsistency.fromCode(-1L)).isNull();
+    }
+}
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConvertersTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConvertersTest.java
index 00238ca38..f686e5ebb 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConvertersTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/alibaba/AliyunConvertersTest.java
@@ -51,6 +51,7 @@ class AliyunConvertersTest {
         SubscriptionEntryVO entry = AliyunConverters.toSubscriptionEntry(data);
 
         assertThat(entry.getFilterMode()).isEqualTo("SQL");
+        assertThat(entry.getConsistency()).isEqualTo("consistent");
     }
 
     @Test
@@ -66,4 +67,22 @@ class AliyunConvertersTest {
 
         assertThat(entry.getFilterMode()).isEqualTo("TAG");
     }
+
+    @Test
+    void toSubscriptionEntryShouldMapTheVendorConsistencyFlagTest() {
+        
assertThat(AliyunConverters.toSubscriptionEntry(subscription(Boolean.TRUE)).getConsistency())
+                .isEqualTo("consistent");
+        
assertThat(AliyunConverters.toSubscriptionEntry(subscription(Boolean.FALSE)).getConsistency())
+                .isEqualTo("inconsistent");
+        
assertThat(AliyunConverters.toSubscriptionEntry(subscription(null)).getConsistency()).isNull();
+    }
+
+    private static ListConsumerGroupSubscriptionsResponseBody.Data 
subscription(Boolean consistency) {
+        return ListConsumerGroupSubscriptionsResponseBody.Data.builder()
+                .topicName("orders")
+                .filterExpression("tag-a")
+                .filterExpressionType("TAG")
+                .consistency(consistency)
+                .build();
+    }
 }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProviderTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProviderTest.java
index 9098b0e57..67371481a 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProviderTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/tencent/TencentInstanceProviderTest.java
@@ -705,6 +705,29 @@ class TencentInstanceProviderTest {
         assertThat(subscriptions.get(0).getTopic()).isEqualTo("orders");
         assertThat(subscriptions.get(0).getExpression()).isEqualTo("*");
         assertThat(subscriptions.get(0).getType()).isEqualTo("TAG");
+        
assertThat(subscriptions.get(0).getConsistency()).isEqualTo("consistent");
+    }
+
+    @Test
+    void getGroupSubscriptionsShouldMapInconsistentAndUnknownConsistencyTest() 
throws Exception {
+        SubscriptionData inconsistent = new SubscriptionData();
+        inconsistent.setTopic("orders");
+        inconsistent.setSubString("*");
+        inconsistent.setExpressionType("TAG");
+        inconsistent.setConsistency(1L);
+        SubscriptionData unknown = new SubscriptionData();
+        unknown.setTopic("payments");
+        unknown.setSubString("tag-a");
+        unknown.setExpressionType("TAG");
+        DescribeTopicListByGroupResponse response = new 
DescribeTopicListByGroupResponse();
+        response.setData(new SubscriptionData[]{inconsistent, unknown});
+        when(client.DescribeTopicListByGroup(any())).thenReturn(response);
+
+        List<SubscriptionEntryVO> subscriptions = 
provider.getGroupSubscriptions(STUDIO_INSTANCE_ID, "GID_test");
+
+        assertThat(subscriptions).hasSize(2);
+        
assertThat(subscriptions.get(0).getConsistency()).isEqualTo("inconsistent");
+        assertThat(subscriptions.get(1).getConsistency()).isNull();
     }
 
     @Test

Reply via email to