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 a2d9b00d4 fix(alert): bound the system-alert listing by reusing the 
paginated query (#7306)
a2d9b00d4 is described below

commit a2d9b00d48a31964bdc95a73cd9faf43ecd36a8b
Author: xdz <[email protected]>
AuthorDate: Mon Oct 26 16:52:05 2026 +0800

    fix(alert): bound the system-alert listing by reusing the paginated query 
(#7306)
    
    * fix(alert): bound the system-alert listing by reusing the paginated query
    GET /api/system-alerts loaded every matching alert into memory and filtered 
domain/instanceId/transition in Java. rmq_system_alert has no retention sweep, 
so the table only grows and the unbounded read grew with it. The paginated 
query already runs every filter in SQL, so the listing now reuses it with the 
first page at the pagination ceiling: the response stays a plain list bounded 
to the newest 100 matching alerts, and the page endpoint remains the complete 
view. The unbounded repos [...]
    * docs(api-spec): bound the system-alert listing at the newest 100
    GET /api/system-alerts now reuses the paginated query, so its plain-list 
response
    carries at most the newest 100 matching alerts; the spec still read as if 
every
    match came back. Point the complete view at the paginated endpoint.
---
 docs/api-spec.md                                   |  3 ++
 .../rocketmq/studio/ops/alert/AlertRepository.java |  2 --
 .../rocketmq/studio/ops/alert/AlertService.java    | 23 ++++++++------
 .../ops/alert/MybatisPlusAlertRepository.java      |  7 ----
 .../studio/ops/alert/AlertServiceTest.java         | 37 ++++++++++++++++------
 .../ops/alert/MybatisPlusAlertRepositoryTest.java  | 19 +++++++----
 6 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/docs/api-spec.md b/docs/api-spec.md
index c32bd4d23..798cb4d18 100644
--- a/docs/api-spec.md
+++ b/docs/api-spec.md
@@ -2413,6 +2413,9 @@ GET /api/system-alerts?level={level}
 
 **Response `data`:** `SystemAlert[]`
 
+> 最多返回**最新 100 条**匹配记录(与分页端点同一个上限);`rmq_system_alert` 没有保留期清理,
+> 无界读取会随表一起增长,需要完整视图走分页端点 `GET /api/system-alerts/page`。
+
 | 字段 | 类型 | 说明 |
 |------|------|------|
 | `id` | `string` | 告警 ID |
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRepository.java
index acda3fe74..79ac05ad7 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertRepository.java
@@ -42,8 +42,6 @@ public interface AlertRepository {
 
     boolean deleteRule(Long id);
 
-    List<SystemAlertVO> findAlerts(String level);
-
     PageResult<SystemAlertVO> findAlerts(String level, int page, int pageSize);
 
     Optional<SystemAlertVO> findAlertById(Long id);
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertService.java 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertService.java
index 7c958018e..4ad25b59a 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/AlertService.java
@@ -59,6 +59,9 @@ public class AlertService {
             "consumer.lag.total", 
SemanticMetric.CONSUMER_LAG_MESSAGES.getKey());
     private static final Pattern DURATION_PATTERN = Pattern.compile(
             "^" + AlertRuleRequestDTO.PROMETHEUS_DURATION_REGEXP + "$");
+    // The same ceiling validateAlertPagination enforces for the page 
endpoints; the legacy
+    // listing reuses it as its result cap.
+    private static final int LIST_ALERTS_MAX = 100;
 
     private final AlertRepository alertRepository;
     private final AlertStateRepository alertStateRepository;
@@ -529,11 +532,6 @@ public class AlertService {
     }
 
 
-    public List<SystemAlertVO> listAlerts(String level) {
-        log.info("Listing system alerts, level={}", level);
-        return alertRepository.findAlerts(level);
-    }
-
     public PageResult<SystemAlertVO> listAlerts(String level, int page, int 
pageSize) {
         validateAlertPagination(page, pageSize);
         String normalizedLevel = StringUtils.hasText(level) ? level.trim() : 
level;
@@ -542,12 +540,17 @@ public class AlertService {
         return alertRepository.findAlerts(normalizedLevel, page, pageSize);
     }
 
+    /**
+     * The listing behind {@code GET /api/system-alerts}. It used to load 
every matching alert
+     * into memory and filter domain/instanceId/transition in Java, but {@code 
rmq_system_alert}
+     * has no retention sweep, so the table only grows and the unbounded read 
grew with it.
+     * The paginated query already runs every filter in SQL, so the listing 
reuses it with the
+     * first page at the pagination ceiling: the response shape stays a plain 
list, bounded to
+     * the newest {@value #LIST_ALERTS_MAX} matching alerts, and the page 
endpoint remains the
+     * complete view.
+     */
     public List<SystemAlertVO> listAlerts(String level, AlertDomain domain, 
String instanceId, String transition) {
-        return listAlerts(level).stream()
-                .filter(alert -> domain == null || domain == alert.getDomain())
-                .filter(alert -> !hasText(instanceId) || 
instanceId.trim().equals(alert.getInstanceId()))
-                .filter(alert -> !hasText(transition) || 
transition.trim().equalsIgnoreCase(alert.getTransition()))
-                .toList();
+        return listAlerts(level, domain, instanceId, transition, 1, 
LIST_ALERTS_MAX).getItems();
     }
 
     public PageResult<SystemAlertVO> listAlerts(String level, AlertDomain 
domain, String instanceId,
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepository.java
 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepository.java
index 6c1cd63ba..24098c320 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepository.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepository.java
@@ -224,13 +224,6 @@ public class MybatisPlusAlertRepository implements 
AlertRepository {
         return id != null && ruleMapper.deleteById(id) > 0;
     }
 
-    @Override
-    public List<SystemAlertVO> findAlerts(String level) {
-        return alertMapper.selectList(alertQuery(level)).stream()
-                .map(MybatisPlusAlertRepository::toAlertVO)
-                .collect(Collectors.toList());
-    }
-
     @Override
     public PageResult<SystemAlertVO> findAlerts(String level, int page, int 
pageSize) {
         Page<RmqSystemAlert> result = alertMapper.selectPage(
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertServiceTest.java
index 793ca52de..c03192226 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/AlertServiceTest.java
@@ -1379,32 +1379,49 @@ class AlertServiceTest {
     }
 
     @Test
-    void listAlertsShouldReturnAlertsForLevelTest() {
+    void listAlertsShouldDelegateToTheBoundedPageQueryTest() {
         SystemAlertVO alert1 = 
SystemAlertVO.builder().id(1L).level(AlertLevel.error)
                 .title("Broker Down").acknowledged(false).build();
         SystemAlertVO alert2 = 
SystemAlertVO.builder().id(2L).level(AlertLevel.error)
                 .title("High Latency").acknowledged(false).build();
-        
when(alertRepository.findAlerts("error")).thenReturn(Arrays.asList(alert1, 
alert2));
+        when(alertRepository.findAlertsPage(any())).thenReturn(PageResult.of(
+                Arrays.asList(alert1, alert2), 2, 1, 100));
 
-        List<SystemAlertVO> result = alertService.listAlerts("error");
+        List<SystemAlertVO> result = alertService.listAlerts(
+                "error", AlertDomain.CLUSTER, "local", "FIRING");
 
-        assertThat(result).hasSize(2);
-        assertThat(result.get(0).getLevel()).isEqualTo(AlertLevel.error);
-        assertThat(result.get(0).getTitle()).isEqualTo("Broker Down");
-        verify(alertRepository).findAlerts("error");
+        assertThat(result).containsExactly(alert1, alert2);
+        org.mockito.ArgumentCaptor<SystemAlertQuery> query =
+                org.mockito.ArgumentCaptor.forClass(SystemAlertQuery.class);
+        verify(alertRepository).findAlertsPage(query.capture());
+        assertThat(query.getValue().level()).isEqualTo("error");
+        assertThat(query.getValue().domain()).isEqualTo(AlertDomain.CLUSTER);
+        assertThat(query.getValue().instanceId()).isEqualTo("local");
+        assertThat(query.getValue().transition()).isEqualTo("FIRING");
+        // The listing is bounded by the same ceiling the paginated endpoint 
enforces.
+        assertThat(query.getValue().page()).isEqualTo(1);
+        assertThat(query.getValue().pageSize()).isEqualTo(100);
     }
 
     @Test
     void listAlertsShouldReturnAllAlertsWhenLevelIsNullTest() {
         SystemAlertVO alert = 
SystemAlertVO.builder().id(1L).level(AlertLevel.warning)
                 .title("Slow Consumer").build();
-        when(alertRepository.findAlerts(null)).thenReturn(List.of(alert));
+        when(alertRepository.findAlertsPage(any())).thenReturn(PageResult.of(
+                List.of(alert), 1, 1, 100));
 
-        List<SystemAlertVO> result = alertService.listAlerts(null);
+        List<SystemAlertVO> result = alertService.listAlerts(null, null, null, 
null);
 
         assertThat(result).hasSize(1);
         assertThat(result.get(0).getLevel()).isEqualTo(AlertLevel.warning);
-        verify(alertRepository).findAlerts(null);
+        org.mockito.ArgumentCaptor<SystemAlertQuery> query =
+                org.mockito.ArgumentCaptor.forClass(SystemAlertQuery.class);
+        verify(alertRepository).findAlertsPage(query.capture());
+        assertThat(query.getValue().level()).isNull();
+        assertThat(query.getValue().domain()).isNull();
+        assertThat(query.getValue().instanceId()).isNull();
+        assertThat(query.getValue().transition()).isNull();
+        assertThat(query.getValue().pageSize()).isEqualTo(100);
     }
 
     @Test
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepositoryTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepositoryTest.java
index f4c5ea2cd..0ce8dc06d 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepositoryTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepositoryTest.java
@@ -218,12 +218,15 @@ class MybatisPlusAlertRepositoryTest {
     }
 
     @Test
-    void findAlertsShouldNormalizeStoredLevelValues() {
+    void findAlertsPageShouldNormalizeStoredLevelValues() {
         RmqSystemAlert entity = new RmqSystemAlert();
         entity.setLevel(" WARNING ");
-        when(alertMapper.selectList(any())).thenReturn(List.of(entity));
+        Page<RmqSystemAlert> result = new Page<>(1, 20);
+        result.setRecords(List.of(entity));
+        when(alertMapper.selectPage(any(Page.class), 
any())).thenReturn(result);
 
-        assertThat(repository.findAlerts(null)).singleElement()
+        assertThat(repository.findAlertsPage(new SystemAlertQuery(null, null, 
null, null,
+                null, null, null, null, 1, 20)).getItems()).singleElement()
                 .satisfies(alert -> assertThat(alert.getLevel()).isEqualTo(
                         
org.apache.rocketmq.studio.common.domain.enums.AlertLevel.warning));
     }
@@ -316,18 +319,20 @@ class MybatisPlusAlertRepositoryTest {
     }
 
     @Test
-    void findAlertsShouldNormalizeLevelIndependentlyOfDefaultLocaleTest() {
-        when(alertMapper.selectList(any())).thenReturn(List.of());
+    void findAlertsPageShouldNormalizeLevelIndependentlyOfDefaultLocaleTest() {
+        when(alertMapper.selectPage(any(Page.class), any())).thenReturn(new 
Page<RmqSystemAlert>(1, 20));
         Locale originalLocale = Locale.getDefault();
 
         try {
             Locale.setDefault(Locale.forLanguageTag("tr-TR"));
-            repository.findAlerts("INFO");
+            repository.findAlertsPage(new SystemAlertQuery("INFO", null, null, 
null,
+                    null, null, null, null, 1, 20));
         } finally {
             Locale.setDefault(originalLocale);
         }
 
-        
verify(alertMapper).selectList(argThat(MybatisPlusAlertRepositoryTest::hasInfoLevelParameter));
+        verify(alertMapper).selectPage(any(Page.class),
+                
argThat(MybatisPlusAlertRepositoryTest::hasInfoLevelParameter));
     }
 
     @Test

Reply via email to