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]

Reply via email to