You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by li...@apache.org on 2026/10/19 11:56:13 UTC

(rocketmq-dashboard) branch rocketmq-studio updated: fix(dlq): scope the group search to the selected instance (#4577)

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 c702d3010 fix(dlq): scope the group search to the selected instance (#4577)
c702d3010 is described below

commit c702d301056c8aa3718a6f463fa43dcd416fd5a0
Author: Apulupie <16...@users.noreply.github.com>
AuthorDate: Mon Oct 19 19:56:07 2026 +0800

    fix(dlq): scope the group search to the selected instance (#4577)
    
    Verified against `rocketmq-studio` at 674e7017d before merging: the defect is still present on the
    current trunk and the change merges cleanly.
    
    Maintainer follow-ups on top of the contributor commit:
    - fix(dlq): clear the search term only when the instance actually changes
    
    Each follow-up commit message records the review finding it addresses.
    
    Locally verified: targeted suites green on the integration branch; a full backend and frontend
    build plus test pass runs on the trunk once this batch lands.
---
 web/src/pages/instance/__tests__/DLQPage.test.tsx | 57 +++++++++++++++++++++++
 web/src/pages/instance/dlq.tsx                    | 12 +++++
 2 files changed, 69 insertions(+)

diff --git a/web/src/pages/instance/__tests__/DLQPage.test.tsx b/web/src/pages/instance/__tests__/DLQPage.test.tsx
index 71001b301..6b068a5ed 100644
--- a/web/src/pages/instance/__tests__/DLQPage.test.tsx
+++ b/web/src/pages/instance/__tests__/DLQPage.test.tsx
@@ -1097,6 +1097,63 @@ describe('DLQ page', () => {
     expect(messageService.listDLQGroups).toHaveBeenCalledTimes(2);
   });
 
+  it('clears the search term when the selected instance changes', async () => {
+    const user = userEvent.setup();
+    renderWithProviders(<DLQPage />);
+
+    await screen.findByText('cg-order');
+    const searchInput = screen.getByPlaceholderText('搜索 Group 名称或 DLQ Topic');
+    await user.type(searchInput, 'ord');
+    await waitFor(() =>
+      expect(messageService.listDLQGroups).toHaveBeenLastCalledWith('instance-1', 'ord', 1, 20),
+    );
+
+    await user.click(screen.getAllByRole('combobox')[0]);
+    await user.click(
+      await screen.findByText('instance-2', { selector: '.ant-select-item-option-content' }),
+    );
+
+    // The old term is meaningless for the new instance: it must not filter the
+    // next request, and the input has to show the cleared value.
+    await waitFor(() => {
+      expect(messageService.listDLQGroups).toHaveBeenLastCalledWith('instance-2', undefined, 1, 20);
+    });
+    expect(searchInput).toHaveDisplayValue('');
+  });
+
+  it('keeps the search term when a completed retry reloads the same instance', async () => {
+    vi.mocked(messageService.resendDLQ).mockResolvedValue({
+      matched: 1,
+      resent: 1,
+      failed: 0,
+      outcome: 'SUCCESS',
+    });
+    const user = userEvent.setup();
+    renderWithProviders(<DLQPage />);
+
+    await screen.findByText('cg-order');
+    const searchInput = screen.getByPlaceholderText('搜索 Group 名称或 DLQ Topic');
+    await user.type(searchInput, 'ord');
+    await waitFor(() =>
+      expect(messageService.listDLQGroups).toHaveBeenLastCalledWith('instance-1', 'ord', 1, 20),
+    );
+
+    const orderRow = screen.getByText('cg-order').closest('tr');
+    if (!orderRow) throw new Error('DLQ group row not found');
+    await user.click(within(orderRow).getByRole('button', { name: '重投消息' }));
+    await user.type(screen.getByPlaceholderText('输入目标 Topic 名称'), 'orders-retry');
+    await user.click(screen.getByRole('button', { name: '确认重投' }));
+
+    // A finished retry bumps `refreshKey`, which is part of the reset scope key.
+    // That reload still targets the same instance, so the term the user is
+    // working with has to survive both the request and the input.
+    await waitFor(() => expect(messageService.resendDLQ).toHaveBeenCalledTimes(1));
+    await waitFor(() =>
+      expect(messageService.listDLQGroups).toHaveBeenLastCalledWith('instance-1', 'ord', 1, 20),
+    );
+    expect(searchInput).toHaveDisplayValue('ord');
+  });
+
   it('ignores a stale group response after changing instances', async () => {
     let resolveFirstInstance!: (page: DLQGroupPage) => void;
     vi.mocked(messageService.listDLQGroups)
diff --git a/web/src/pages/instance/dlq.tsx b/web/src/pages/instance/dlq.tsx
index a6cb0a8dc..566d2d780 100644
--- a/web/src/pages/instance/dlq.tsx
+++ b/web/src/pages/instance/dlq.tsx
@@ -170,6 +170,18 @@ const DLQPage = () => {
     setLoading(true);
   }
 
+  // The search term filters the group list of one instance only, so switching
+  // instances has to drop it — otherwise the first request for the new instance
+  // is filtered by a term that can never match there. Kept separate from the
+  // `scopeKey` block above on purpose: that key also moves when a completed
+  // retry bumps `refreshKey`, and a reload of the same instance must keep the
+  // term the user is still working with.
+  const [prevInstanceId, setPrevInstanceId] = useState(selectedInstanceId);
+  if (prevInstanceId !== selectedInstanceId) {
+    setPrevInstanceId(selectedInstanceId);
+    setSearch('');
+  }
+
   useEffect(() => {
     const requestId = ++groupRequestIdRef.current;