messere1 opened a new pull request, #6454:
URL: https://github.com/apache/rocketmq-dashboard/pull/6454
### What problem does this PR solve?
Resubmission of #6134 with the scope its review asked for: every
await-then-mutate path in `alerts.tsx`, not just the save path.
- `handleSubmit` and `handleTest` both `await form.validateFields()` before
flipping `submitting`/`testing`, so the confirm and test-run buttons only lock
after validation resolves and React re-renders. A repeat click in that window
re-enters the handler and starts a duplicate
`createAlertRule`/`updateAlertRule`/`testAlertRule` request — and a rule test
is not a read-only operation.
- The dialog stays closable while a save is pending, so the X button, Esc,
the mask and both cancel buttons tear the form down mid-save; the request still
completes against an already-dismissed dialog, and a duplicate create surfaces
the contradictory "created" + "save failed" toast pair (the server's
semantic-fingerprint dedup keeps it from landing two rows —
`uk_alert_rule_semantic_fingerprint` plus the dedup in `AlertService`).
- The row and bulk actions
(`handleToggle`/`handleDelete`/`handleBulkToggle`/`handleBulkDelete`) guard
entry with `isActionRunning`, which reads rendered state — two clicks in one
tick both pass before the loading re-render commits, which is the same window
in a different shape.
### What is changed and how it works?
- `handleSubmit` takes a synchronous `submitInFlightRef` and `handleTest` a
`testInFlightRef`; both flip their state before validation starts and release
in `finally`, so nothing changes for the happy path.
- The four row/bulk actions share one `actionInFlightRef`, set synchronously
at entry and released in each `finally` (the buttons keep rendering their
existing loading/disabled states from `actionId`/`bulkAction`).
- The modal becomes `closable`/`keyboard`/`maskClosable={false}` while a
submission is in flight, and both cancel paths funnel through one
`closeRuleModal` that no-ops while `submitInFlightRef` is held. A hung request
releases the lock via the HTTP client's 30s axios timeout.
- The export/import paths and `loadMetricCapabilities` are out of scope by
design: they flip their in-flight state before their first `await`, and metric
loads are already request-versioned.
### Verification
- Red on the unpatched tip, per new test:
- `submits an alert rule edit only once and stays open while the request
is pending` fails at the synchronous `ant-btn-loading` assertion (the call
count alone does not discriminate in jsdom — rc-field-form supersedes the first
in-flight validation when the second click re-enters, so the lock assertion is
what pins the window);
- `runs one rule test per click while the first run is pending` fails the
same way on the test-run button;
- `runs one row toggle per click while the first request is pending` fails
with `toggleAlertRule` called twice when both clicks land inside one `act` —
before the loading re-render commits, the rendered `isActionRunning` guard
cannot stop the second entry.
- The mid-flight cancel assertion re-queries with
`screen.getByRole('dialog')` and pins that the form still holds its values: a
closed modal keeps its node mounted but hides the wrap with `display:none`, so
the role query only matches while the dialog is genuinely open (no reliance on
`toBeInTheDocument` against the mounted-but-closed node, and no redundant
call-count assertion outside the `waitFor`).
- Green with the patch: `npx vitest run
src/pages/ops/__tests__/AlertsPage.test.tsx` — 36/36 pass.
- `npx eslint` on both touched files — 0 errors; the 5 warnings are present
on the unpatched tip as well.
--
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]