tju-yxq opened a new issue, #5404:
URL: https://github.com/apache/rocketmq-dashboard/issues/5404

   ## Problem
   
   The K8s certificate page's delete action tracks its in-flight request in a 
**single unguarded `deletingId` slot**. Deleting a second certificate while the 
first request is still running breaks both rows' UI state: the second 
`setDeletingId(certB.id)` immediately makes the first row's spinner disappear 
and re-enables its delete button mid-request, and the first handler's `finally 
{ setDeletingId(null) }` later clears the second row's spinner as well. 
Re-clicking the re-enabled first row re-POSTs `deleteK8sCert` for a certificate 
that is already deleted (or being deleted), surfacing a spurious error toast 
for a delete that actually succeeded — the operator is left believing a removal 
failed when it did not.
   
   ## What did you do (steps to reproduce)?
   
   1. Open **Cluster > K8s 证书配置** with at least two certificates.
   2. Click 删除 on the first row and confirm; while the request is on the wire 
(a slow backend makes this easy), click 删除 on the second row and confirm.
   3. The first row's spinner vanishes the moment the second delete starts, and 
its button looks clickable again; clicking it fires a second `deleteK8sCert` 
for the same id.
   4. When the first handler's `finally` runs, the second row's spinner 
disappears too — both rows now show as idle while requests are still pending.
   
   ## What did you expect to see?
   
   Each row's delete keeps its own in-flight spinner; a row cannot be 
re-submitted while its delete is pending; one delete does not disturb another.
   
   ## What did you see instead?
   
   A single slot clobbered by whichever delete started last, re-enabling 
in-flight rows and double-POSTing deletes.
   
   ## Root cause
   
   `web/src/pages/cluster/certs.tsx`:
   
   - Line 63: `const [deletingId, setDeletingId] = useState<number | 
null>(null);` — one slot for all rows.
   - Lines 121-132 (`handleDelete`): no entry guard, `setDeletingId(cert.id)` 
at the start and `setDeletingId(null)` in `finally`.
   - Line 242: `loading={deletingId === cert.id}` — false for every other row 
the moment another delete starts.
   
   The repository's row-action idiom for exactly this situation is the guarded 
per-key Set — `AlertRuleAssetList.handleExport` 
(`web/src/components/AlertRuleAssetList.tsx` lines 142-155): a synchronous 
`exportingNamesRef.current.has(...)` guard plus `setExportingNames(new 
Set(...))` so concurrent row actions keep independent spinners. The certificate 
page implements neither the per-key pattern nor a single-flight entry guard 
(`if (deletingId !== null) return;`).
   
   ## Expected behavior
   
   - In-flight deletes are tracked per certificate id: concurrent deletes of 
different certificates each keep their spinner.
   - A repeated confirmation for a row whose delete is already pending is a 
no-op (synchronous ref guard).
   - Successful deletes still remove the row and show the success message; 
failures still toast the server reason.
   
   ## Acceptance criteria
   
   - [ ] Regression proof: on the current code, starting a second delete 
mid-flight clears the first row's loading state; with the fix both rows show 
loading simultaneously.
   - [ ] Confirming the same row twice while its delete is pending fires 
`deleteK8sCert` exactly once.
   - [ ] Resolving both pending deletes removes both rows and shows both 
success messages.
   - [ ] The single-delete flow (confirm, await, row disappears) is unchanged.
   
   ## Environment
   
   Branch `rocketmq-studio` at `6a68042f`; file: 
`web/src/pages/cluster/certs.tsx`.
   
   ## Duplicate check
   
   Searched open and closed issues for `cert delete`; the only certificate-page 
item is #852 (closed — null request bodies on the write APIs, a different 
defect). Nothing covers the delete in-flight state.
   


-- 
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]

Reply via email to