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 ea290419 perf: remove N+1 admin calls from listConsumerGroups (#1446)
ea290419 is described below
commit ea290419bfa415f4bc61d158bf53d5bc0ead2a9b
Author: Yu Xinqiang <[email protected]>
AuthorDate: Tue Aug 11 00:26:38 2026 +0800
perf: remove N+1 admin calls from listConsumerGroups (#1446)
* [ISSUE #1445] Remove N+1 admin calls from listConsumerGroups
The list operation called enrichGroupWithConnectionInfo for every
group, making 2 admin API calls per group. For 100 groups this meant
200 admin calls and minutes-long page load. This fix removes the
live enrichment from the list, keeping it for the detail page only.
Fixes #1445
* refactor(metadata): drop dead enrichment helper after list de-enrichment
After removing the N+1 enrichment from listConsumerGroups,
enrichGroupWithConnectionInfo and its dedicated executeForInstance
helper have no remaining callers: the group detail page loads
connection and lag info through getGroupSubscriptions and
getGroupProgress. Remove both helpers along with the test that
asserted list-time enrichment.
---
.../provider/apache/RocketMQMetadataProvider.java | 46 ++--------------------
.../apache/RocketMQMetadataProviderTest.java | 16 --------
2 files changed, 3 insertions(+), 59 deletions(-)
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProvider.java
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProvider.java
index 31055ae8..da3dea7b 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProvider.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProvider.java
@@ -182,11 +182,9 @@ public class RocketMQMetadataProvider implements
MetadataProvider {
vo.setCreatedAt(entity.getCreatedAt());
vo.setUpdatedAt(entity.getUpdatedAt());
- if (StringUtils.hasText(instanceId)) {
- enrichGroupWithConnectionInfo(vo, entity.getName(),
instanceId);
- } else if (hasAdmin()) {
- enrichGroupWithConnectionInfo(vo, entity.getName(), null);
- }
+ // Live connection info (online instances, lag) is intentionally
NOT fetched
+ // during list operations to avoid N+1 admin API calls. It is
loaded on
+ // demand when viewing a single group's detail page.
result.add(vo);
}
return result;
@@ -420,44 +418,6 @@ public class RocketMQMetadataProvider implements
MetadataProvider {
// ── Helper methods ──────────────────────────────────────────────────
- private void enrichGroupWithConnectionInfo(ConsumerGroupVO vo, String
groupName, String instanceId) {
- try {
- ConsumerConnection conn = executeForInstance(instanceId,
- admin -> admin.examineConsumerConnectionInfo(groupName));
- if (conn != null) {
- if (conn.getConnectionSet() != null) {
- vo.setOnlineInstances(conn.getConnectionSet().size());
- }
- if (conn.getSubscriptionTable() != null) {
- vo.setSubscribedTopics(new
ArrayList<>(conn.getSubscriptionTable().keySet()));
- }
- }
- } catch (Exception ignored) {
- // Group may be offline, that's fine
- }
-
- // Try to get lag info
- try {
- ConsumeStats stats = executeForInstance(instanceId, admin ->
admin.examineConsumeStats(groupName));
- if (stats != null && stats.getOffsetTable() != null) {
- long totalLag = 0;
- for (OffsetWrapper ow : stats.getOffsetTable().values()) {
- totalLag += Math.max(0, ow.getBrokerOffset() -
ow.getConsumerOffset());
- }
- vo.setTotalLag(totalLag);
- }
- } catch (Exception ignored) {
- // No stats available
- }
- }
-
- private <T> T executeForInstance(String instanceId,
MqAdminExtFactory.AdminAction<T> action) {
- if (StringUtils.hasText(instanceId)) {
- return runtimeAdminClientResolver.execute(instanceId, action);
- }
- return adminExecute(action);
- }
-
private String filterMode(String expressionType) {
if ("SQL92".equals(expressionType)) {
return "SQL";
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProviderTest.java
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProviderTest.java
index 41def9bc..3259cd90 100644
---
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProviderTest.java
+++
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMetadataProviderTest.java
@@ -44,7 +44,6 @@ import static org.mockito.Mockito.lenient;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -103,21 +102,6 @@ class RocketMQMetadataProviderTest {
assertThat(groups.get(0).getConsumeType()).isEqualTo(ConsumeType.CLUSTERING);
}
- @Test
- void listConsumerGroupsShouldUseSelectedInstanceForRuntimeEnrichment() {
- RmqGroup entity = new RmqGroup();
- entity.setName("group-a");
- entity.setInstanceId("instance-a");
- entity.setClusterId("cluster-a");
- when(groupMapper.selectList(any())).thenReturn(List.of(entity));
- when(runtimeAdminClientResolver.execute(eq("instance-a"),
any())).thenReturn(null);
-
- List<ConsumerGroupVO> groups =
newProvider().listConsumerGroups("instance-a", null, null);
-
-
assertThat(groups).singleElement().extracting(ConsumerGroupVO::getName).isEqualTo("group-a");
- verify(runtimeAdminClientResolver, times(2)).execute(eq("instance-a"),
any());
- }
-
@Test
void getTopicRoutesShouldUseSelectedInstanceRuntimeClient() {
List<BrokerRouteVO> routes =
List.of(BrokerRouteVO.builder().brokerName("broker-a").build());