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 c271c1ef6 fix(web): reject deleting a missing alert rule in mock mode 
(#7122)
c271c1ef6 is described below

commit c271c1ef6892ffa4789fd213cc12792dd22067e2
Author: Qingyuan Wang <[email protected]>
AuthorDate: Wed Oct 28 00:41:00 2026 +0800

    fix(web): reject deleting a missing alert rule in mock mode (#7122)
    
    Mock mode's deleteAlertRule returned success for a rule that was not there, 
so the
    mock surface and the real API disagreed about the one case a caller has to 
handle.
    Throw "Alert rule not found" instead, matching the server.
    
    The test conflicted with #7140, which added semantic-fingerprint 
de-duplication to
    the mock createAlertRule; both sets of cases are kept, and the new fixture 
uses a
    distinct metric so the de-duplication cannot swallow it.
---
 web/src/services/opsService.test.ts | 21 +++++++++++++++++++++
 web/src/services/opsService.ts      |  3 ++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/web/src/services/opsService.test.ts 
b/web/src/services/opsService.test.ts
index 650b8cde3..4eb78aeb4 100644
--- a/web/src/services/opsService.test.ts
+++ b/web/src/services/opsService.test.ts
@@ -237,6 +237,27 @@ describe('ops service mock data', () => {
     }
   });
 
+  it('rejects deleting a missing alert rule in mock mode', async () => {
+    const rule = await createAlertRule({
+      name: 'deleted-rule-marker',
+      metric: 'mock.delete.missing',
+      channels: ['email'],
+    });
+    await deleteAlertRule(rule.id, 'CLUSTER');
+
+    await expect(deleteAlertRule(rule.id, 'CLUSTER')).rejects.toThrow(
+      `Alert rule not found: ${rule.id}`,
+    );
+    await expect(deleteAlertRule(rule.id, 'BUSINESS')).rejects.toThrow(
+      `Alert rule not found: ${rule.id}`,
+    );
+    // The two rejections above delete by the id createAlertRule handed out, 
which is Date.now()
+    // based. An id that was never issued keeps the case deterministic 
regardless of that.
+    await expect(deleteAlertRule(999999, 'CLUSTER')).rejects.toThrow(
+      'Alert rule not found: 999999',
+    );
+  });
+
   it('imports and exports alert rules within the selected domain only', async 
() => {
     const imported = await importAlertRulesTransfer(
       {
diff --git a/web/src/services/opsService.ts b/web/src/services/opsService.ts
index 1779a24f2..ed00ebe42 100644
--- a/web/src/services/opsService.ts
+++ b/web/src/services/opsService.ts
@@ -348,7 +348,8 @@ export async function deleteAlertRule(
 ): Promise<void> {
   if (isMockMode()) {
     const idx = alertRulesState[domain].findIndex((rule) => rule.id === id);
-    if (idx >= 0) alertRulesState[domain].splice(idx, 1);
+    if (idx < 0) throw new Error(`Alert rule not found: ${id}`);
+    alertRulesState[domain].splice(idx, 1);
     return;
   }
   return opsApi.deleteAlertRule(id, domain);

Reply via email to