yyqdbngt opened a new pull request, #5340:
URL: https://github.com/apache/rocketmq-dashboard/pull/5340
### Which Issue(s) This PR Fixes
- Fixes #5261
### Brief Description
`Client.request` decoded the Studio payload with
`json.Unmarshal(envelope.Data, out)`
(`rmqctl/internal/studio/client.go:161`) and `CallTool` passes a `*any` as
`out`, so
`encoding/json` represented every JSON number as a `float64`. An int64 field
above
2^53 was silently rounded before the output layer ever saw it:
`9007199254740993` printed as `9007199254740992` in table, json and yaml
output
alike. `types.DecodeMutationOutput` re-encodes the same decoded value to
inspect it,
so mutation summaries inherited the rounded number as well.
The fix decodes those payloads through the new `types.DecodeJSON`, which uses
`json.Decoder.UseNumber()` and then normalises integer literals that fit in
`int64` back to `int64` (`types.normalizeJSONNumbers`, applied to
`map[string]any`
and `[]any` trees). `types.DecodeMutationOutput` does the same for the
`plan` and
`result` fields it re-decodes. Non-integer literals (`1.5`, `1e300`) and
integers
outside int64 keep the `float64` they had before, and typed (non-`any`)
decode
targets still go straight to `json.Unmarshal`, so no caller sees a behaviour
change
other than the preserved int64.
Note on scope: the passthrough path in `client.go` and the mutation summary
were the
two decode sites named in the issue; the MCP stdio proxy forwards the
server's raw
JSON unchanged and decodes only typed structs, so it is not affected.
### How Did You Test This Change?
Red run on the unmodified tree, green run after the fix - same command, same
two
tests (`rmqctl/internal/studio/int64_precision_test.go`). The tests start a
stub
Studio endpoint with `httptest` and answer a real `CallTool`, so they
exercise the
HTTP client, the decode and the output layer together.
```powershell
$ cd rmqctl
$ go test ./internal/studio/ -run Precision -count=1 -v
=== RUN TestCallToolPreservesInt64BeyondFloat64Precision
int64_precision_test.go:63: decoded items[0].msgOffset =
9.007199254740992e+15 (float64), want int64 9007199254740993
--- FAIL: TestCallToolPreservesInt64BeyondFloat64Precision (0.01s)
=== RUN TestMutationSummaryPreservesInt64BeyondFloat64Precision
int64_precision_test.go:121: decoded mutation msgOffset =
9.007199254740992e+15 (float64), want int64 9007199254740993
--- FAIL: TestMutationSummaryPreservesInt64BeyondFloat64Precision (0.00s)
FAIL github.com/apache/rocketmq-dashboard/rmqctl/internal/studio 0.091s
```
```powershell
$ go test ./internal/studio/ -run Precision -count=1 -v
=== RUN TestCallToolPreservesInt64BeyondFloat64Precision
--- PASS: TestCallToolPreservesInt64BeyondFloat64Precision (0.01s)
=== RUN TestMutationSummaryPreservesInt64BeyondFloat64Precision
--- PASS: TestMutationSummaryPreservesInt64BeyondFloat64Precision (0.00s)
PASS
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/studio 0.090s
```
The first test asserts the exact `int64` in the decoded tree and then
renders the
same payload three ways: `json` and `yaml` through `output.Structured`, the
table
through `output.MapsFromAny` + `output.Rows`. Each rendering must contain
`9007199254740993` and must not contain `9007199254740992`; the yaml
rendering is
additionally pinned to the unquoted `msgOffset: 9007199254740993` so the
integer
stays a number rather than becoming a string. The second test asserts the
value
survives `types.DecodeMutationOutput` and the `output.ToolCallSummary`
summary.
Rest of the module after the fix:
```powershell
$ go test ./internal/... ./cmd/... -count=1
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/catalog 0.038s
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/catalog/generate
0.084s
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/config 0.048s
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/output 0.047s
ok github.com/apache/rocketmq-dashboard/rmqctl/internal/studio 0.092s
ok github.com/apache/rocketmq-dashboard/rmqctl/cmd 1.668s
$ go vet ./internal/... ./cmd/... # clean, gofmt -l clean
```
(`go test ./...` also runs `rmqctl/scripts`, whose packaging test shells out
to
`bash` and fails on this Windows box for that unrelated reason; it fails
identically
before the change.)
### Checklist
- [x] One coherent change; unrelated modifications are not bundled in
- [x] Commit subject follows Conventional Commits
- [x] Tests added or updated for non-trivial changes
- [ ] New UI text has both Chinese and English entries under `web/src/i18n/`
- not applicable, no UI text
- [ ] Architecture constraints stay green (`mvn test` runs the ArchUnit
checks) - not applicable, Go module only
- [x] New source files carry the ASF license header
- [ ] Documentation touched where behaviour changed (README / `docs/` /
in-app help) - not applicable, no user-facing documentation states the old
rounding behaviour; the new doc comments on `types.DecodeJSON` carry the
contract
--
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]