RockteMQ-AI commented on code in PR #3168:
URL: 
https://github.com/apache/rocketmq-dashboard/pull/3168#discussion_r3937761250


##########
server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java:
##########
@@ -122,13 +141,38 @@ private PageResult<DLQGroupVO> listDLQGroups(MQAdminExt 
adminExt, String search,
         long offset = Pagination.pageOffset(page, pageSize);
         int from = (int) Math.min(offset, dlqTopics.size());
         int to = (int) Math.min(offset + pageSize, dlqTopics.size());
-        List<DLQGroupVO> groups = dlqTopics.subList(from, to).stream()
-                .map(topic -> buildDLQGroup(adminExt,
-                        
topic.substring(MixAll.DLQ_GROUP_TOPIC_PREFIX.length()), topic))
-                .toList();
+        List<String> pageTopics = dlqTopics.subList(from, to);
+        List<DLQGroupVO> groups = loadGroupStatsInParallel(adminExt, 
pageTopics);
         return PageResult.of(groups, dlqTopics.size(), page, pageSize);
     }
 
+    private List<DLQGroupVO> loadGroupStatsInParallel(MQAdminExt adminExt, 
List<String> pageTopics) {
+        List<Future<DLQGroupVO>> futures = new ArrayList<>(pageTopics.size());
+        for (String topic : pageTopics) {
+            String groupName = 
topic.substring(MixAll.DLQ_GROUP_TOPIC_PREFIX.length());
+            futures.add(statsExecutor.submit(() -> buildDLQGroup(adminExt, 
groupName, topic)));
+        }
+        List<DLQGroupVO> groups = new ArrayList<>(futures.size());
+        for (Future<DLQGroupVO> future : futures) {
+            groups.add(awaitGroupStats(future));
+        }
+        return groups;
+    }
+
+    private DLQGroupVO awaitGroupStats(Future<DLQGroupVO> future) {
+        try {
+            return future.get(STATS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            future.cancel(true);
+        } catch (InterruptedException e) {
+            future.cancel(true);
+            Thread.currentThread().interrupt();
+        } catch (ExecutionException e) {
+            // buildDLQGroup reports single-topic failures inside the row 
itself.

Review Comment:
   When `awaitGroupStats` falls back (timeout / interrupt / execution 
exception), the returned `DLQGroupVO` has no `groupName` or `dlqTopic` set — 
the user will see a blank row in the DLQ table with only `UNAVAILABLE` status.
   
   Consider passing `groupName` and `dlqTopic` into `awaitGroupStats` so the 
fallback can populate them:
   ```java
   private DLQGroupVO awaitGroupStats(Future<DLQGroupVO> future, String 
groupName, String dlqTopic) {
       try {
           return future.get(STATS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
       } catch (TimeoutException e) {
           future.cancel(true);
       } catch (InterruptedException e) {
           future.cancel(true);
           Thread.currentThread().interrupt();
       } catch (ExecutionException e) {
           // single-topic failure
       }
       return DLQGroupVO.builder()
               .groupName(groupName).dlqTopic(dlqTopic)
               .statsAvailable(false).status("UNAVAILABLE").build();
   }
   ```
   And update `loadGroupStatsInParallel` to pass them through.



##########
server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQDLQProvider.java:
##########
@@ -122,13 +141,38 @@ private PageResult<DLQGroupVO> listDLQGroups(MQAdminExt 
adminExt, String search,
         long offset = Pagination.pageOffset(page, pageSize);
         int from = (int) Math.min(offset, dlqTopics.size());
         int to = (int) Math.min(offset + pageSize, dlqTopics.size());
-        List<DLQGroupVO> groups = dlqTopics.subList(from, to).stream()
-                .map(topic -> buildDLQGroup(adminExt,
-                        
topic.substring(MixAll.DLQ_GROUP_TOPIC_PREFIX.length()), topic))
-                .toList();
+        List<String> pageTopics = dlqTopics.subList(from, to);
+        List<DLQGroupVO> groups = loadGroupStatsInParallel(adminExt, 
pageTopics);
         return PageResult.of(groups, dlqTopics.size(), page, pageSize);
     }
 
+    private List<DLQGroupVO> loadGroupStatsInParallel(MQAdminExt adminExt, 
List<String> pageTopics) {
+        List<Future<DLQGroupVO>> futures = new ArrayList<>(pageTopics.size());
+        for (String topic : pageTopics) {
+            String groupName = 
topic.substring(MixAll.DLQ_GROUP_TOPIC_PREFIX.length());
+            futures.add(statsExecutor.submit(() -> buildDLQGroup(adminExt, 
groupName, topic)));
+        }
+        List<DLQGroupVO> groups = new ArrayList<>(futures.size());
+        for (Future<DLQGroupVO> future : futures) {
+            groups.add(awaitGroupStats(future));
+        }
+        return groups;
+    }
+
+    private DLQGroupVO awaitGroupStats(Future<DLQGroupVO> future) {
+        try {
+            return future.get(STATS_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            future.cancel(true);
+        } catch (InterruptedException e) {
+            future.cancel(true);
+            Thread.currentThread().interrupt();
+        } catch (ExecutionException e) {
+            // buildDLQGroup reports single-topic failures inside the row 
itself.
+        }

Review Comment:
   The `ExecutionException` catch block silently swallows the underlying 
exception. Consider adding a `log.debug` or `log.warn` so operators can 
diagnose slow/failing brokers:
   ```java
   } catch (ExecutionException e) {
       log.warn("Failed to load DLQ stats for topic, row marked UNAVAILABLE", 
e.getCause());
   }
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to