This is an automated email from the ASF dual-hosted git repository. lizhimins pushed a commit to branch rocketmq-studio in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git
commit 24047c4fed0983473185859fd1c4b2f88dd9685a Author: aias00 <[email protected]> AuthorDate: Thu Jul 23 23:21:41 2026 -0700 fix: sort queried messages by store time (#519) Sort message query results by storeTime in descending order so latest messages appear first. --- web/src/api/message.test.ts | 37 +++++++++++++++++++++++++++++++++++++ web/src/api/message.ts | 12 +++++++++++- web/src/services/messageService.ts | 3 ++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/web/src/api/message.test.ts b/web/src/api/message.test.ts index 1f76234e..5119a1a5 100644 --- a/web/src/api/message.test.ts +++ b/web/src/api/message.test.ts @@ -48,6 +48,43 @@ describe('message API', () => { await expect(queryMessages(params)).resolves.toEqual([]); }); + it('sorts message query results by store time descending', async () => { + mock.onGet('/messages').reply(200, { + code: 200, + data: [ + { + msgId: 'msg-old', + topic: 'orders', + tag: 'created', + key: 'order-1', + body: '{}', + storeTime: '2026-07-23T10:00:00.000Z', + bornHost: '10.0.0.1:1000', + storeHost: '10.0.0.2:10911', + properties: {}, + size: 2, + }, + { + msgId: 'msg-new', + topic: 'orders', + tag: 'created', + key: 'order-2', + body: '{}', + storeTime: 1784804400000, + bornHost: '10.0.0.1:1001', + storeHost: '10.0.0.2:10911', + properties: {}, + size: 2, + }, + ], + }); + + await expect(queryMessages({ topic: 'orders' })).resolves.toMatchObject([ + { msgId: 'msg-new' }, + { msgId: 'msg-old' }, + ]); + }); + it('unwraps trace records with numeric timestamps', async () => { const trace = { nodes: [ diff --git a/web/src/api/message.ts b/web/src/api/message.ts index 70dd7b90..716c387c 100644 --- a/web/src/api/message.ts +++ b/web/src/api/message.ts @@ -42,6 +42,16 @@ export interface MessageQuery { endTime?: number; } +const toStoreTimestamp = (storeTime: MessageRecord['storeTime']): number => { + if (typeof storeTime === 'number') return storeTime; + + const parsed = Date.parse(storeTime); + return Number.isNaN(parsed) ? 0 : parsed; +}; + +export const sortMessagesByStoreTimeDesc = (messages: MessageRecord[]): MessageRecord[] => + [...messages].sort((a, b) => toStoreTimestamp(b.storeTime) - toStoreTimestamp(a.storeTime)); + // Matches mock/dlq.ts export interface DLQGroup { groupName: string; @@ -55,7 +65,7 @@ export interface DLQGroup { // ─── Messages ─────────────────────────────────────────────────── export async function queryMessages(params: MessageQuery) { const res = await client.get<{ data: MessageRecord[] }>('/messages', { params }); - return res.data.data; + return sortMessagesByStoreTimeDesc(res.data.data); } export async function getMessageTrace(msgId: string) { diff --git a/web/src/services/messageService.ts b/web/src/services/messageService.ts index 71e33d2c..81896b59 100644 --- a/web/src/services/messageService.ts +++ b/web/src/services/messageService.ts @@ -1,5 +1,6 @@ import { USE_MOCK } from '../config'; import * as messageApi from '../api/message'; +import { sortMessagesByStoreTimeDesc } from '../api/message'; import type { MessageQuery, MessageRecord, TraceRecord, DLQGroup } from '../api/message'; import { mockMessages, mockMessageTraces } from '../mock/messages'; import { mockDLQGroups } from '../mock/dlq'; @@ -10,7 +11,7 @@ export async function queryMessages(params: MessageQuery): Promise<MessageRecord if (params.topic) result = result.filter((m) => m.topic === params.topic); if (params.key) result = result.filter((m) => m.key.includes(params.key!)); if (params.msgId) result = result.filter((m) => m.msgId === params.msgId); - return result as unknown as MessageRecord[]; + return sortMessagesByStoreTimeDesc(result as unknown as MessageRecord[]); } return messageApi.queryMessages(params); }
