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


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new bc33d7098 fix(message): map trace node statuses on the key lookup too 
(#4746)
bc33d7098 is described below

commit bc33d709877b8bc62b2d2869eb1f00157cf15c1f
Author: 烤化の初雪 <[email protected]>
AuthorDate: Thu Sep 24 17:46:12 2026 +0800

    fix(message): map trace node statuses on the key lookup too (#4746)
    
    test(message): pin the key lookup null and node-default contracts
    
    The fix leaves the response normalisation on the key lookup, so the two
    branches it introduces need their own coverage: a trace the server
    answers with a null payload stays null (the "no trace found" contract the
    key lookup already had), and a trace without a nodes array yields an
    empty node list instead of leaking the missing field to the Steps
    component.
    
    fix(message): map trace node statuses on the key lookup too
    
    GET /messages/trace-by-key returns the same broker node statuses as
    GET /messages/{msgId}/trace ("finish" | "failed" | ...), but only the
    msgId wrapper normalised them through mapTraceNodeStatus. A failed node
    reached through the key lookup therefore kept its raw "failed" status,
    which Ant Design Steps cannot render and which the trace diagnostics
    panel does not recognise as a failure, so a broken trace was reported as
    healthy.
    
    Map the nodes in getMessageTraceByKey the same way, keeping the existing
    null (no trace found) contract.
---
 web/src/api/message.test.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++
 web/src/api/message.ts      | 14 ++++++++++--
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/web/src/api/message.test.ts b/web/src/api/message.test.ts
index 33a06d263..a190fbc0e 100644
--- a/web/src/api/message.test.ts
+++ b/web/src/api/message.test.ts
@@ -21,6 +21,7 @@ import client from './client';
 import {
   consumeMessageDirectly,
   getMessageTrace,
+  getMessageTraceByKey,
   queryMessagePage,
   queryMessages,
 } from './message';
@@ -173,6 +174,58 @@ describe('message API', () => {
     expect(mapped.consumerStatus).toEqual([]);
   });
 
+  it('maps backend trace node statuses on the key lookup too', async () => {
+    const trace = {
+      nodes: [
+        {
+          title: 'Produce',
+          timestamp: 1784246400000,
+          status: 'failed',
+          costTime: 1,
+          description: 'x',
+        },
+        {
+          title: 'Consume',
+          timestamp: 1784246400000,
+          status: 'finish',
+          costTime: 1,
+          description: 'x',
+        },
+        {
+          title: 'Unknown',
+          timestamp: 1784246400000,
+          status: 'something-else',
+          costTime: 1,
+          description: 'x',
+        },
+      ],
+      consumerStatus: [],
+    };
+    mock
+      .onGet('/messages/trace-by-key', { params: { key: 'order-1', instanceId: 
'instance-1' } })
+      .reply(200, { code: 200, data: trace });
+
+    const mapped = await getMessageTraceByKey('order-1', 'instance-1');
+    expect(mapped?.nodes.map((node) => node.status)).toEqual(['error', 
'finish', 'wait']);
+  });
+
+  it('keeps the key lookup null and node-default contracts', async () => {
+    mock
+      .onGet('/messages/trace-by-key', { params: { key: 'missing', instanceId: 
'instance-1' } })
+      .reply(200, { code: 200, data: null });
+
+    await expect(getMessageTraceByKey('missing', 
'instance-1')).resolves.toBeNull();
+
+    mock
+      .onGet('/messages/trace-by-key', { params: { key: 'no-nodes', 
instanceId: 'instance-1' } })
+      .reply(200, { code: 200, data: { consumerStatus: [] } });
+
+    await expect(getMessageTraceByKey('no-nodes', 
'instance-1')).resolves.toEqual({
+      consumerStatus: [],
+      nodes: [],
+    });
+  });
+
   it('encodes message IDs before requesting trace records', async () => {
     const trace = {
       nodes: [],
diff --git a/web/src/api/message.ts b/web/src/api/message.ts
index bb31baabf..7d9ee46c9 100644
--- a/web/src/api/message.ts
+++ b/web/src/api/message.ts
@@ -209,8 +209,18 @@ export async function getMessageTraceByKey(
   if (instanceId !== undefined) params.instanceId = instanceId;
   if (topic !== undefined) params.topic = topic;
   if (traceTopic !== undefined && traceTopic.trim()) params.traceTopic = 
traceTopic.trim();
-  const res = await client.get<{ data: TraceRecord 
}>('/messages/trace-by-key', { params });
-  return res.data.data;
+  const res = await client.get<{ data: TraceRecord | null 
}>('/messages/trace-by-key', { params });
+  const trace = res.data.data;
+  if (!trace) {
+    return null;
+  }
+  return {
+    ...trace,
+    nodes: (trace.nodes ?? []).map((node) => ({
+      ...node,
+      status: mapTraceNodeStatus(node.status),
+    })),
+  };
 }
 
 // ─── DLQ ────────────────────────────────────────────────────────

Reply via email to