Wang1rrr opened a new issue, #4864:
URL: https://github.com/apache/rocketmq-dashboard/issues/4864

   ### Before Creating the Doc Report
   
   - [x] I have searched the [open 
issues](https://github.com/apache/rocketmq-dashboard/issues) and found no 
similar issue.
   
   ### Which Documentation
   
   `docs/api-spec.md` - section 4 "集群管理 Cluster / NameServer / Proxy" and the 
"接口速查" index. Verified against `rocketmq-studio` @ `4c697f07`.
   
   ### What Is Wrong
   
   `ProxyController` 
(`server/src/main/java/org/apache/rocketmq/studio/cluster/proxy/ProxyController.java`)
 exposes six endpoints under `/api/proxies`. The spec documents exactly one of 
them, and documents that one incorrectly.
   
   | endpoint | controller | 接口速查 | section 4 |
   | --- | --- | --- | --- |
   | `GET /api/proxies` | `:43` | missing | missing |
   | `GET /api/proxies/topology` | `:49` | missing | missing |
   | `POST /api/proxies/addresses` | `:54` | missing | missing |
   | `DELETE /api/proxies/addresses` | `:60` | missing | missing |
   | `POST /api/proxies/config/reload` | `:66` | missing | missing |
   | `POST /api/proxies/restart` | `:72` | row 17 | 4.11 - contract is wrong |
   
   **4.11 does not match the code.** It shows a single-field request body and a 
`{ success: boolean }` response:
   
   - The body is `RestartProxyDTO`, which has **two** `@NotBlank` fields, 
`clusterId` and `addr`. A caller who follows the spec sends `{"addr": 
"127.0.0.1:8081"}` and is rejected by bean validation with `400 clusterId is 
required`.
   - The response type is `Result<Void>`, so `data` is `null`. There is no 
`success` field to read.
   - The endpoint cannot currently succeed at all: 
`ClusterService.restartProxy` (`:626`) resolves the cluster, checks the address 
is registered, then unconditionally throws `unsupportedOperation("Proxy 
restart")` (`:654`) - a `501 Proxy restart is not implemented by the current 
cluster provider`. The console still shows a success toast 
(`web/src/pages/cluster/index.tsx:1722`), so the spec is the only place a 
reader can learn what the call really does.
   
   **The five missing endpoints carry behaviour that cannot be guessed from the 
paths.** Every one of these is a trap for an integrator, and all of it is only 
discoverable by reading three layers of Java:
   
   - **There are two unrelated notions of "proxy".** `GET /api/proxies` returns 
the *cluster-registered* proxies (`ClusterVO.proxies` via 
`ClusterService.listProxies`, no probing at all), while `/topology`, 
`/addresses` and `/config/reload` operate on *Studio's own in-memory address 
list* (`ProxyAddressService`, seeded with `127.0.0.1:8081`). `GET 
/api/proxies/topology` takes no `clusterId` and ignores cluster registration 
entirely - a reader who just called `GET /api/proxies?clusterId=x` will assume 
the topology is for that cluster.
   - **Two different status vocabularies for the same concept.** 
`ProxyVO.status` is `ClusterStatus` (`healthy` / `warning` / `error` / 
`offline`), while `ProxyTopologyVO.status` is the probe outcome (`UP` / 
`PARTIAL` / `DOWN`). Nothing says they are different scales.
   - **The probe is bounded and never fails the request.** One TCP probe per 
port with a 2 s timeout (`HEALTH_PROBE_TIMEOUT_MILLIS`, `:68`), all probes in 
parallel on a bounded pool, and a 10 s total budget 
(`TOPOLOGY_TOTAL_TIMEOUT_MILLIS`, `:77`). Probes that do not finish in time are 
reported as unreachable, so a rack full of dead proxies yields `DOWN` rows 
rather than a 5xx or a hung request.
   - **`remotingPort` is derived, not read.** `deriveRemotingPort` (`:267`) 
maps `8081 -> 8080` and `8080 -> 8081` and returns `null` for anything else, 
because the pairing cannot be assumed for custom ports. When it is `null`, 
`remotingReachable` is hard-`false` and only the gRPC side is probed. 
`latencyMs` is `-1` whenever gRPC is unreachable.
   - **Malformed registered addresses vanish.** `buildTopology` (`:174`) skips 
any address that does not match `host:port` / `[ipv6]:port` with only a 
server-side log line, so the response can contain fewer rows than the address 
list.
   - **Address mutation is validated and audited, and is not persisted.** 
`addProxyAddr` (`:274`) / `removeProxyAddr` (`:286`) normalise through 
`normalizeProxyAddr` (`:59` pattern, ports 1-65535, IPv6 literal checked) and 
raise `400` otherwise. Adding a duplicate is idempotent and does not 
double-record the audit entry; removing the current address moves 
`currentProxyAddr` to the first remaining one, or `""` when the list empties; 
removing an unknown address records a `FAILED` audit row and returns `404`. The 
whole list lives in a `LinkedHashSet` field, so a Studio restart drops every 
address an operator added.
   - **`/config/reload` is the only proxy write that actually reaches a 
proxy.** It requires the address to be registered under `clusterId` (`:308` -> 
`ClusterService.requireProxy`, `404` otherwise), then POSTs to 
`http://{addr}/admin/reloadConfig` (`RELOAD_PATH`, `:65`). Non-2xx and 
connection failures both surface as `502`, anything else as `500`, and the 
success and failure paths each record a `RELOAD_PROXY_CONFIG` audit entry. 
`{"success": true}` is the only non-exception outcome - it never answers 
`success: false`.
   
   ### Suggested Change
   
   Rewrite 4.11 against the code (two-field body, `data: null`, 400/404/501 
error table, and a sentence saying the provider does not implement restart 
yet), then add the five missing endpoints as 4.12-4.16 in the format the 
document already uses - `**Query Parameters:**` / `**Request Body:**` tables, a 
`**Response data:**` field table, prose for the cross-cutting rules, and 
`**错误响应:**` tables. The K8s certificate sections move from 4.12-4.15 to 
4.17-4.20 so the proxy endpoints stay grouped next to "重启 Proxy"; nothing else 
in the repository references those numbers by section (`rg -n "4\.1[2-5]" 
--glob '*.md'` matches only the four headings themselves).
   
   Append the five rows to the end of 接口速查 rather than inserting them at row 
17, matching how rows 90-98 were appended.
   
   Deliberately **not** bundled here, so this stays one coherent change:
   
   - `ProxyCompatController` (`/api/proxy/homePage.query`, 
`/api/proxy/addProxyAddr.do`, `/api/proxy/removeProxyAddr.do`) is also 
undocumented. It is the v2.1.0 compatibility surface and deserves its own 
subsection.
   - 4.4 重启 Broker has the same defect - it documents `{ success: boolean, 
message: string }` while `ClusterController.restartBroker` (`:89`) returns only 
`message` and `ClusterService.restartBroker` (`:570`) always throws `501`.
   
   ### Are You Willing to Submit a Pull Request?
   
   - [x] Yes, I am willing to submit a pull request.


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