tju-yxq opened a new issue, #2210:
URL: https://github.com/apache/rocketmq-dashboard/issues/2210
## Problem
Studio refuses to delete an instance registration until it can confirm
through the selected vendor provider that the instance has no managed Topics or
Consumer Groups:
```java
int topicCount = provider.countTopics(id);
int consumerGroupCount = provider.countGroups(id);
```
That guard is necessary when the remote system is reachable, but it also
makes a stale registration impossible to remove when the preflight cannot run.
Examples include a decommissioned NameServer or Proxy endpoint, expired cloud
credentials, a deleted cloud instance, DNS/network failure, or a provider API
outage. In those cases `countTopics` or `countGroups` throws before
`instanceRepository.deleteById` is reached.
This conflicts with the UI's cloud-instance wording that deletion only
removes the Studio registration and does not release the cloud RocketMQ
instance. A registration whose remote instance is already gone can remain
permanently stuck in Studio.
## Reproduction
A deterministic service test against the current `rocketmq-studio` head
(`eb44e159`) stubs an existing instance and makes `countTopics` throw
`IllegalStateException("broker unavailable")`.
Observed behavior:
- the provider exception escapes;
- `instanceRepository.deleteById` is never called;
- no existing request option permits removal of the stale registration.
This is a unit-level reproduction; it does not claim a live Broker or
cloud-provider test.
## Required safety contract
A force option must not turn the existing managed-resource guard into an
unconditional bypass.
1. A normal delete continues to run the authoritative provider preflight.
2. If the preflight succeeds and finds any Topic or Consumer Group, deletion
returns a conflict. Supplying `force=true` must not override this known result.
3. If the preflight succeeds and both counts are zero, deletion proceeds
normally.
4. If the preflight cannot determine the counts, the normal request returns
a stable machine-readable error distinct from the managed-resource conflict.
5. Only after that specific failure may the UI offer a second, explicit
warning that removes the Studio registration without claiming to delete or
validate remote resources.
6. A force request must still attempt the preflight. It may proceed only
when that attempt is unavailable; it must still reject known managed resources.
7. A forced removal must be visible in the operation audit, including
`forced=true`, an unavailable-preflight marker, and a bounded/sanitized failure
summary that cannot copy credentials or unbounded provider text into the audit
record.
8. Existing concurrent-delete behavior, Apache AdminClient release rules,
and the 404 result for an already removed registration must remain intact.
## API and UI contract
Use an instance-specific delete request instead of adding `force` to the
common delete DTO used by unrelated resources.
The backend response for an unavailable preflight needs a stable error
identifier, so the frontend does not inspect an English message substring. The
instance page should:
- send the ordinary delete request after the existing confirmation;
- show the second destructive confirmation only for the
unavailable-preflight identifier;
- never offer force removal for the managed-resources conflict;
- resend the request with `force=true` only after explicit confirmation;
- report a failure if the forced request itself does not complete.
## Tests
Backend coverage should include:
- empty-instance normal deletion;
- Topics and Consumer Groups blocking both normal and force requests;
- unavailable preflight rejecting a normal request without repository/audit
side effects;
- unavailable preflight allowing an explicit force removal;
- sanitized and bounded forced-audit detail;
- Apache endpoint release after a successful forced removal;
- concurrent deletion still returning 404;
- controller request binding and the machine-readable unavailable-preflight
response.
Frontend coverage should include:
- force serialized in the instance API request;
- the second confirmation appears only for the exact error identifier;
- confirming it sends `force=true`;
- ordinary conflicts and unrelated failures never expose the force path;
- successful deletion still reloads the latest active filters.
## Related work
- #1235 introduced the authoritative live-count preflight; this issue
preserves that protection.
- #1726 concerned converting one unsupported Tencent count path into an HTTP
501 response. It was closed because `UnsupportedOperationException` already had
a handler. A structured failure alone does not provide an explicit, safe way to
remove a stale registration.
- #2000 covers the separate concurrent-delete zero-row result.
- #1592 implements Tencent group counting and does not address
unreachable/decommissioned providers.
The expected implementation spans the instance-specific backend
request/error/preflight/audit contract and the frontend API/confirmation flow.
The production change is expected to exceed 100 lines because both boundaries
must change together; tests are not counted toward that estimate.
--
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]