Wang1rrr opened a new issue, #4868: URL: https://github.com/apache/rocketmq-dashboard/issues/4868
### Before Creating the Bug Report - [x] I have searched the [open issues](https://github.com/apache/rocketmq-dashboard/issues) of this repository and believe that this is not a duplicate. - [x] This is a defect in RocketMQ Studio, not a usage question and not a defect in another Apache RocketMQ repository. - [x] I can reproduce this on the current `rocketmq-studio` branch (the Studio trunk the pull request template points at), commit `4c697f07acde460e2344375cb1f82669f5b270fd`. ### Studio Version ``` branch: rocketmq-studio git commit id: 4c697f07acde460e2344375cb1f82669f5b270fd deployed as: built from source ``` ### Runtime Environment ``` OS: Windows 11 (development box); the defect is a contract declaration, so the host does not matter MySQL: not required - reproduced from the sources and from the web unit tests browser (for UI issues): any; the affected console page is web/src/pages/instance/topic.tsx ``` ### Connected RocketMQ Cluster ``` RocketMQ version: any - all three providers (Apache, Aliyun, Tencent) build the same VO access mode: Direct / Proxy Local / Proxy Cluster / cloud - the response shape is identical deployment: any cluster where the console can send a test message to a topic ``` ### Build Toolchain ``` node: v22 (web/ package.json engines), npm ci from web/package-lock.json java: 21 (server/pom.xml, maven.compiler.release=21) ``` ### Describe the Bug `POST /api/topics/send` answers with `SendMessageVO`, whose `sendTime` is a primitive `long` (`server/src/main/java/org/apache/rocketmq/studio/instance/topic/SendMessageVO.java:30`). Every provider fills it with `System.currentTimeMillis()`: - `provider/apache/RocketMQAdminClientImpl.java:555` - `provider/alibaba/AliyunInstanceProvider.java:483` - `provider/tencent/TencentInstanceProvider.java:600` So the wire value is a JSON **number** of epoch milliseconds. The AI tool contract agrees: `server/src/main/resources/tool-catalog/tools/message.yaml:526` declares `sendTime: type: integer`, and `ops/ai/tool/contract/message/MessageSendOutput.java:26` is `long sendTime`. Three declarations say the opposite, and they are the ones a web or third-party integrator actually reads: | place | claims | | --- | --- | | `docs/api-spec.md:891` | `sendTime` \| `string` \| 发送时间 (ISO 8601) | | `docs/api-spec.md:912` | `"sendTime": "2026-07-08T10:30:45.123Z"` in the response example | | `web/src/api/metadata.ts:289` | `sendTime: string;` on `SendTopicMessageResult` | The mock data layer is written to the wrong type, so the console serves two different shapes for the same field depending on the data mode: `web/src/services/topicService.ts:241` returns `new Date().toISOString()` when `isMockMode()`, and the real API returns `1783506645123`. Nothing catches it - `tsc` is happy because the mock satisfies the declared (wrong) type, and the real response is never type-checked. The two existing fixtures disagree with each other, which is how the drift stayed invisible: - `web/src/api/metadata.test.ts:139` stubs the endpoint with `sendTime: 1` - a number, i.e. what the server really sends - and then asserts only `toMatchObject({ msgId: 'msg-1' })`, so the field is never checked; - `web/src/pages/instance/__tests__/TopicPage.test.tsx:188` stubs the service with `sendTime: '2026-01-02T00:00:00Z'` - a string, i.e. what the type wrongly promises. Today the console only reads `result.msgId` (`web/src/pages/instance/topic.tsx:1455`), so this is latent rather than visible: the defect is that the documented and declared contract is wrong, that mock mode and real mode are not interchangeable for this field, and that the first caller who renders or formats `sendTime` - the obvious next step for a "message sent" confirmation, and the reason the field exists - will be written against a string and handed a number. `dayjs(1783506645123)` and `new Date('1783506645123')` do not agree, and `String(sendTime).length` checks or `.slice()` formatting silently produce garbage. ### Steps to Reproduce 1. On `rocketmq-studio` @ `4c697f07`, read `SendMessageVO.sendTime` and the three provider call sites that set it - the server sends epoch millis. 2. Read `docs/api-spec.md` §5.8 (发送消息到 Topic) and `web/src/api/metadata.ts:289` - both promise an ISO-8601 string. 3. Run the console in mock data mode and call `sendTopicMessage`: `topicService.ts:241` returns `new Date().toISOString()`. Switch to a real cluster and the same call returns a number. 4. `cd web && npx vitest run src/api/metadata.test.ts src/pages/instance/__tests__/TopicPage.test.tsx` - both pass, one fixture using `1` and the other using `'2026-01-02T00:00:00Z'`, because no assertion pins the type. ### What Did You Expect to See? One contract, stated the same way everywhere: `sendTime` is epoch milliseconds, matching `SendMessageVO`, the three providers and the `message.yaml` tool schema. The mock data layer should return the same shape as the real API so the two modes are interchangeable, and a test should pin it. ### What Did You See Instead? The spec, its JSON example and the TypeScript type all declare an ISO-8601 string; the mock implements that string; the server returns a number; and the two test fixtures encode the two contradictory answers without either failing. ### Additional Context The fix should align the declarations with the server, not the server with the declarations: epoch millis is what all three providers already produce and what the AI tool schema (`message.yaml:526`) already publishes, so changing `SendMessageVO` to a formatted string would break the tool contract and every existing consumer of `rmq.message.send`. Scope of the correction: `docs/api-spec.md` §5.8 (field table and response example), `web/src/api/metadata.ts`, the mock branch in `web/src/services/topicService.ts`, the `TopicPage.test.tsx` fixture, an assertion on the pass-through in `metadata.test.ts`, and a new `topicService.test.ts` case that fails if mock mode ever drifts from the API shape again. ### 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]
