zmuxuny opened a new pull request, #7395: URL: https://github.com/apache/rocketmq-dashboard/pull/7395
### Which Issue(s) This PR Fixes Fixes #7164. Replacement for #7165, which was closed automatically for inactivity. The linked issue was also closed by the stale bot. This preserves the original four-file implementation and authorship, refreshed onto `rocketmq-studio` at `7abf8adaf660d75f2d686bbe8741be76c3a5ddd3`. Candidate: `e74a93306771f1f9467ab4713f3d7b8b1aa419a7`. ### Brief Description Native reconciliation needs only the newest instance/labels for each active alert key. The existing batched query materializes every matching historical event, including descriptions, before Java keeps the first event per key. Repeated reminders therefore increase JDBC results and Java allocation even when the active keys do not change. Rank scalar event IDs by `(rule_id, fingerprint)` with `time DESC, id DESC`, then fetch only the winning metadata columns. Preserve batching, exact requested key pairs, domain/instance isolation, timestamp tie-breaking, and missing-event behavior. A global `LIMIT` cannot replace per-key selection because one hot key can consume the limit. This bounds application-side result volume by requested keys. It does **not** bound database history scanning, sorting, or window-ranking work. No schema, index, dependency, API, retention, or configuration change is included. The native fingerprint contract matters: producers generate canonical lowercase SHA-256 hex keys. This change does not preserve arbitrary mixed-case fingerprints under MySQL's case-insensitive collation. The diagnostic below makes that limitation explicit rather than claiming universal equivalence. Fresh overlap review on 2026-11-04 found no same-branch replacement or equivalent result-bound implementation in the inspected searches. The actual #5879 diff only adds transactions to `replaceRule` and `deleteAcknowledgedAlerts`; it does not modify this metadata path. Merged #7306 bounds the public alert-list endpoint, not native state reconciliation. Recent acknowledgement, notification-dispatch, rule-test-window, and import-lifecycle changes were also checked and are not bundled here. AI assistance was used for implementation review, test execution, and analysis of the recorded results. ### How Did You Test This Change? Validation on 2026-11-04 with Java 21.0.13, Maven 3.9.9, and an isolated MySQL 8.0.46 instance using the existing schema and default `utf8mb4_0900_ai_ci` collation. No external database or broker was used. **Committed H2 regression and surrounding tests** - `mvn ... -Dtest=AlertStateMetadataQueryTest test`: exact candidate 4/4 passed. Replacing only the repository implementation with its exact base blob made the two history-size cases fail on the expected mapper-row assertions: expected 2, actual 2,002/4,002. There were no errors. Restoring the candidate passed 4/4. - The eight-suite selection `AlertStateMetadataQueryTest,MybatisPlusAlertStateRepositoryTest,NativeAlertProcessorTest,AlertStateMachineTest,AlertSchemaMigrationTest,AlertFingerprintTest,AlertRuleStateLifecycleTest,NativeAlertClusterCorrelationTest` passed 87/87. - The normal Maven test lifecycle ran compilation, RAT, and Checkstyle; no rules or assertions were weakened. `git diff --check` passed. The commands above abbreviate the common offline cache/settings, single-fork, heap, and Mockito-agent options. The exact commands, logs, and fresh Surefire reports were retained. The negative keeps the new mapper method present but unused so tests compile; it exercises the original production `selectList`, not a mocked result or the entire base tree. **Real MySQL reproduction, plans, and allocation observations** A temporary local copy of the same four regression cases used real MyBatis and MySQL, with identical data volumes and assertions. It is audit instrumentation, not an additional committed test class. Candidate 4/4 passed; exact-base repository control produced the same two expected assertion failures and no errors; restored candidate passed 4/4. For 1,000 / 2,000 historical events per active key: - Base materialized 2,002 / 4,002 event rows; candidate and restored candidate materialized 2 / 2 metadata rows. All historical rows remained stored. - Base mapped descriptions contained 2,302,300 / 4,602,300 characters; candidate descriptions were not selected. Base labels contained 52,058 / 104,058 characters versus 58 / 58 in the candidate. - Current-thread allocated bytes around the actual MyBatis `Executor.query` were 12,127,936 / 23,618,344 for base versus 54,128 / 54,008 for candidate. These are synthetic JVM thread-allocation observations, not peak/retained heap, process memory, network bytes, or a production latency benchmark. `EXPLAIN FORMAT=JSON` and `EXPLAIN ANALYZE` used the actual mapper BoundSql and MyBatis parameter binding. MySQL still scanned/sorted/ranked 2,002 / 4,002 historical rows before two winner primary-key lookups. In a hot/quiet-key control with 2,203 stored events, the feed index read 2,103 rows, the window processed 2,003, and all four requested keys were returned; a naive global `LIMIT 5` represented only the hot key. No constant-time database or guaranteed latency improvement is claimed. Timestamp ties, older/null timestamps, cross-pair exclusions, domain/instance isolation, missing metadata, ACKED states, and the no-active-state control were checked. The hot/quiet control passed before and after restoration. The mixed-case boundary was also reproduced: with a lowercase active key, an older lowercase event, and a newer uppercase variant, the base's Java filtering retains one active state. MySQL's case-insensitive window groups the variants together, the candidate selects the uppercase event, and the final exact Java lookup yields no active state. This repeats after restoration. Passing this diagnostic documents the limitation; it does not fix it. Compatibility here is limited to the canonical lowercase native keys described above. **Retained environment failures and corrections** - The first MySQL attempt had 3 passing cases and 1 setup error: a JDBC handshake timed out before the empty-state case created its schema. The first harness opened thousands of fixture connections. Reusing one physical fixture connection per case reduced that overhead without changing queries, data, or assertions; the subsequent candidate/base/restore sequence completed as reported above. Connection count has not been proven to be the timeout's cause. The original error is retained and is not counted as a negative control. - A later related-suite invocation accidentally exported a MySQL URL to the H2/dev-profile `AlertBulkMutationTransactionTest`. It reported 27 tests, 0 assertion failures, and 4 context errors because the H2 driver rejected that URL. The other 23 cases passed: 20 alert-repository unit tests, 2 real-MySQL state-mapper cases, and 1 real-MySQL native-evaluation transaction case. After clearing datasource environment overrides, the unchanged four bulk-transaction cases passed under their declared H2 profile. The original mixed-profile run remains recorded as failed. The MySQL server shut down normally, temporary audit sources were removed, and all four committed file bytes were checked against the exact candidate. No full local backend aggregate, packaging build, production benchmark, or new exact-head hosted-CI pass is claimed. Hosted CI must establish its own result for this replacement. ### Checklist - [x] One coherent change; the original four-file scope is preserved - [x] Conventional commit subject - [x] Real mapper regression tests with `Test` method suffixes - [x] No new UI text, API, dependency, workflow, schema, or index changes - [x] New source carries the ASF license header - [x] Self-reviewed implementation, negative controls, and validation limitations - [ ] Full exact-head CI, including architecture checks, still needs to run -- 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]
