unbridled-41 opened a new issue, #4783: URL: https://github.com/apache/rocketmq-dashboard/issues/4783
### Studio Version Trunk `rocketmq-studio` @ `4c697f07` (line references are as of that commit). ### Problem `POST /api/alert-rules/update` and `POST /api/cluster-alert-rules/update` replace every editable field of a rule, but an update body that simply omits an optional field does not clear it. `MybatisPlusAlertRepository.replaceRule` (`server/src/main/java/org/apache/rocketmq/studio/ops/alert/MybatisPlusAlertRepository.java:141-146`) builds the entity with `toRuleEntity` and calls `ruleMapper.updateById(entity)`. MyBatis-Plus's default NOT_NULL update strategy omits null entity fields from the UPDATE's SET clause, so the previous value silently survives. The service path makes the mismatch worse: `AlertService.updateRule` (`AlertService.java:190-223`) validates the submitted VO, replaces the stored rule, and returns the **submitted** VO. So the API responds with the field cleared (`consumerGroup`: null, `severity`: null, ...), the UI renders the cleared value, and the next `GET` shows the old value back. Fields affected (all nullable in `rmq_alert_rule`, all accepted-as-null by `NativeAlertRulePolicy.validate` and `AlertRuleRequestDTO`): `thresholdUnit`, `duration`, `channels`, `description`, `brokerName`, `clusterName`, `severity`, `instanceId` (for Prometheus-rule metrics only — native metrics require it), `consumerGroup`, `topic`, `notificationTemplate`. A concrete failure: a business `consumer.lag.total` rule scoped to `consumerGroup="G1"` cannot be re-scoped to all groups through the update API. The stale filter keeps narrowing alert evaluation while the operator believes it was removed. ### Evidence 1. `NativeAlertRulePolicy.validate` only rejects a missing `instanceId` for native metrics (`NativeAlertRulePolicy.java:66-71`); a null `consumerGroup`/`topic`/`severity`/`duration` passes (`AlertRuleDuration.parse(null)` returns ZERO). 2. `replaceRule` → `ruleMapper.updateById(toRuleEntity(rule))` with the entity's optional fields null — MyBatis-Plus skips them in the SET clause (no global `update-strategy` override in `application.yml`, no `@TableField(updateStrategy=...)` on `RmqAlertRule`). 3. The codebase already documents this exact behaviour for the sibling path and works around it: `NameserverRegistryService.clearOmittedOptionalColumns` (`cluster/nameserver/NameserverRegistryService.java:147-172`, merged PR #4466, "MyBatis-Plus updateById omits null entity fields... assign those columns explicitly"), and `MybatisPlusInstanceRepository.java:128-131` does the same for a cleared credential reference. The alert-rule path is the one missing it. ### Impact - Scope filters (`instanceId`/`consumerGroup`/`topic`/`brokerName`/`clusterName`) cannot be cleared, so alerts keep evaluating against a stale narrower scope than the UI shows. - `severity`/`duration`/`channels`/`notificationTemplate`/`description` silently revert to their previous values after an update that omitted them, contradicting the 200 response. - The silent divergence between the response and the stored row is undetectable from the client. ### Expected behavior An update that omits an optional field clears it, and the stored rule matches the response — the same contract the registry and instance paths already implement. ### Related work - #4466 (merged 2026-09-21): the same defect class fixed for instance and nameserver-registry optional columns; did not touch alert rules. - #4277/#4276/#4275 (closed/unmerged attempts in the same family) confirm the pattern is recognised by the project. - #4326 (open): toggling wipes FIRING/ACK state — a different field-lifecycle defect on the same table. - #4748 (open, mine): reconcile abort for rules without a metric — unrelated. ## PR Fix: #… (opened together with this issue). -- 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]
