Wang1rrr opened a new pull request, #4869:
URL: https://github.com/apache/rocketmq-dashboard/pull/4869
### Which Issue(s) This PR Fixes
- Fixes #4868
### Brief Description
`POST /api/topics/send` returns `SendMessageVO.sendTime` as a primitive
`long` of epoch millis (`SendMessageVO.java:30`, set with
`System.currentTimeMillis()` in all three providers:
`RocketMQAdminClientImpl.java:555`, `AliyunInstanceProvider.java:483`,
`TencentInstanceProvider.java:600`), and the AI tool schema already publishes
it as an integer (`tool-catalog/tools/message.yaml:526`,
`MessageSendOutput.java:26`).
Three declarations promised an ISO-8601 string instead, and the mock layer
implemented that promise - so mock mode and real mode returned different shapes
for the same field, with no test pinning either:
- `docs/api-spec.md` §5.8 field table (`sendTime | string | 发送时间 (ISO
8601)`) and its response example
- `web/src/api/metadata.ts:289` `sendTime: string;` on
`SendTopicMessageResult`
- `web/src/services/topicService.ts:241` mock branch returning `new
Date().toISOString()`
This aligns all of them with the server. The direction matters: changing
`SendMessageVO` to emit a formatted string would break the published tool
schema and every consumer of `rmq.message.send`, so the declarations move, not
the wire format.
- `web/src/api/metadata.ts` - `sendTime: number` with a one-line note that
it mirrors `SendMessageVO.sendTime`
- `web/src/services/topicService.ts` - mock returns `Date.now()`, so mock
mode is now interchangeable with the real API for this field
- `docs/api-spec.md` §5.8 - the field table says `number` / Unix 毫秒时间戳, and
the example response uses `1783506645123`, which is
`Date.parse('2026-07-08T10:30:45.123Z')` - the same instant the example already
showed, so the sample stays semantically identical
- `web/src/pages/instance/__tests__/TopicPage.test.tsx:188` - the fixture
that encoded the wrong string shape now uses `Date.parse(...)`
- `web/src/api/metadata.test.ts` - the pass-through assertion now checks
`sendTime: 1`, so the API layer pins the numeric shape it was already stubbing
- `web/src/services/topicService.test.ts` - new case `reports the send time
as epoch millis, the shape the API returns`
Impact today is latent rather than visible:
`web/src/pages/instance/topic.tsx:1455` reads only `result.msgId`. What the PR
removes is the trap - the next caller that renders or formats `sendTime` (the
obvious next step for a send confirmation) would have been written against a
string and handed `1783506645123`.
### How Did You Test This Change?
```
cd web
npx vitest run src/services/topicService.test.ts src/api/metadata.test.ts
src/pages/instance/__tests__/TopicPage.test.tsx
Test Files 3 passed (3)
Tests 47 passed (47)
npx tsc -b # exit 0
npx eslint src/api/metadata.ts src/api/metadata.test.ts
src/services/topicService.ts src/services/topicService.test.ts
src/pages/instance/__tests__/TopicPage.test.tsx
# exit 0, no findings
npx prettier --check --end-of-line auto <the same five files>
All matched files use Prettier code style!
```
Mutation-checked, because a type-only fix is exactly the kind of change that
can pass while pinning nothing. Reverting only the mock branch to `new
Date().toISOString()` (leaving the new test in place) fails the new case and
nothing else:
```
npx vitest run src/services/topicService.test.ts
FAIL src/services/topicService.test.ts > topic service mock data > reports
the send time as epoch millis, the shape the API returns
AssertionError: expected 'string' to be 'number' // Object.is equality
Test Files 1 failed (1)
Tests 1 failed | 8 passed (9)
```
Restoring `Date.now()` returns that file to `9 passed (9)`.
Documentation side: `git diff --numstat` is `2 2 docs/api-spec.md` - the two
`sendTime` lines only, no other section, anchor or index row touched, CRLF
preserved and no BOM, so the diff carries no whitespace churn. `1783506645123`
was produced by `Date.parse` on the string the example already contained and
round-trips back to `2026-07-08T10:30:45.123Z` (asserted in the patch script).
No Java changed, so `mvn test` and the ArchUnit checks are unaffected.
### Checklist
- [x] One coherent change; unrelated modifications are not bundled in
- [x] Commit subject follows Conventional Commits (`feat:` / `fix:` /
`refactor:` / `chore:` / `docs:` / `perf:`)
- [x] Tests added or updated for non-trivial changes, test methods named
`...Test` (web: one new vitest case, two fixtures corrected; no Java behaviour
changed)
- [x] New UI text has both Chinese and English entries under `web/src/i18n/`
(no new UI text; the spec edit keeps the document's existing Chinese wording)
- [x] Architecture constraints stay green (`mvn test` runs the ArchUnit
checks) - no Java changed
- [x] New source files carry the ASF license header (no new source files)
- [x] Documentation touched where behaviour changed (README / `docs/` /
in-app help) - `docs/api-spec.md` §5.8 corrected in the same change, since the
wrong contract was documented there too
--
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]