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