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 22bf3a300 fix(ai): stop grading a group healthy from an unresolved 
consumer lag (#5091)
22bf3a300 is described below

commit 22bf3a3009cb408f01f866cb77c11fc68d1b5e34
Author: 烤化の初雪 <[email protected]>
AuthorDate: Thu Oct 1 17:28:38 2026 +0800

    fix(ai): stop grading a group healthy from an unresolved consumer lag 
(#5091)
    
    rmq.group.detail's health ladder enumerated two "signal unavailable" inputs
    (consume statistics missing, connection inventory missing) and then tested 
only
    `totalLag > 0`. The lag-unknown sentinel is -1 (ConsumerLagResolver.UNKNOWN,
    what the provider writes when any queue diff is the broker's own -1 for gRPC
    consumers), so a group with online consumers and an unresolved lag fell 
through
    to the final `else` and was reported as HEALTHY, i.e. "nothing accumulated" 
was
    asserted from data the server itself marks undeterminable.
    
    Test the sentinel before the lag-derived branches and answer UNKNOWN with a
    reason, the way the two other unavailable signals already do. The
    connection-derived verdicts stay as they were: a group with no online 
consumer
    is still WARNING, because that verdict does not depend on the lag.
    
    Co-authored-by: unbridled-41 <[email protected]>
---
 .../tool/handler/group/GroupDetailToolHandler.java |  5 ++++
 .../group/ConsumerGroupReadToolHandlersTest.java   | 34 ++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
index 4a5ac0542..26a062a3a 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/GroupDetailToolHandler.java
@@ -85,6 +85,11 @@ public class GroupDetailToolHandler implements 
ToolHandler<GroupDetailInput, Gro
         } else if (group.getOnlineInstances() == 0) {
             status = "WARNING";
             reasons.add("The group has no online consumer.");
+        } else if (group.getTotalLag() < 0) {
+            // The -1 sentinel means the lag could not be resolved (a queue 
whose diff is unknown),
+            // so no verdict may be derived from it, not even the "nothing 
accumulated" one.
+            status = "UNKNOWN";
+            reasons.add("Consumer lag information is unavailable.");
         } else if (group.getTotalLag() > 0) {
             status = "WARNING";
             reasons.add("The group has accumulated messages.");
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
index 000b1be5a..82f2e06ea 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/group/ConsumerGroupReadToolHandlersTest.java
@@ -27,6 +27,7 @@ import 
org.apache.rocketmq.studio.instance.topic.MetadataService;
 import org.apache.rocketmq.studio.ops.ai.tool.contract.group.GroupDetailInput;
 import org.apache.rocketmq.studio.ops.ai.tool.contract.group.GroupDetailOutput;
 import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.apache.rocketmq.studio.provider.apache.ConsumerLagResolver;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -172,6 +173,39 @@ class ConsumerGroupReadToolHandlersTest {
         assertThat(output.onlineInstances()).isEqualTo(-1);
     }
 
+    @Test
+    void detailMarksHealthUnknownWhenTheConsumerLagIsUnavailableTest() {
+        group.setOnlineInstances(1);
+        group.setTotalLag(ConsumerLagResolver.UNKNOWN);
+        when(metadataService.consumerGroupRuntimeView("instance-a", 
"group-a")).thenReturn(group);
+        when(metadataService.consumerGroupConfigurations("instance-a", 
"group-a")).thenReturn(List.of(group));
+        when(metadataService.getGroupSubscriptions("instance-a", 
"group-a")).thenReturn(List.of());
+        when(metadataService.getGroupProgress("instance-a", 
"group-a")).thenReturn(List.of());
+
+        GroupDetailOutput output = new GroupDetailToolHandler(metadataService)
+                .execute(new GroupDetailInput("instance-a", "group-a", null), 
context());
+
+        assertThat(output.health().status()).isEqualTo("UNKNOWN");
+        assertThat(output.health().reasons()).contains("Consumer lag 
information is unavailable.");
+        assertThat(output.totalLag()).isEqualTo(ConsumerLagResolver.UNKNOWN);
+    }
+
+    @Test
+    void detailKeepsTheConnectionWarningWhenTheConsumerLagIsUnavailableTest() {
+        group.setOnlineInstances(0);
+        group.setTotalLag(ConsumerLagResolver.UNKNOWN);
+        when(metadataService.consumerGroupRuntimeView("instance-a", 
"group-a")).thenReturn(group);
+        when(metadataService.consumerGroupConfigurations("instance-a", 
"group-a")).thenReturn(List.of(group));
+        when(metadataService.getGroupSubscriptions("instance-a", 
"group-a")).thenReturn(List.of());
+        when(metadataService.getGroupProgress("instance-a", 
"group-a")).thenReturn(List.of());
+
+        GroupDetailOutput output = new GroupDetailToolHandler(metadataService)
+                .execute(new GroupDetailInput("instance-a", "group-a", null), 
context());
+
+        assertThat(output.health().status()).isEqualTo("WARNING");
+        assertThat(output.health().reasons()).contains("The group has no 
online consumer.");
+    }
+
     @Test
     void detailWithoutOnlineConsumersKeepsProgressAndClientsEmpty() {
         ConsumerGroupVO offline = new ConsumerGroupVO();

Reply via email to