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 f24be26c5 fix(producer): invalidate connection queries when the group 
changes (#7208)
f24be26c5 is described below

commit f24be26c58933f7017f9f9986f5cb862348cdb9e
Author: messere <[email protected]>
AuthorDate: Mon Oct 26 20:32:56 2026 +0800

    fix(producer): invalidate connection queries when the group changes (#7208)
    
    * fix(producer): invalidate connection queries when the group changes
---
 web/src/pages/studio/Producer.tsx                |  10 ++-
 web/src/pages/studio/__tests__/Producer.test.tsx | 103 +++++++++++++++++++++++
 2 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/web/src/pages/studio/Producer.tsx 
b/web/src/pages/studio/Producer.tsx
index c606a2967..5dbdc45d9 100644
--- a/web/src/pages/studio/Producer.tsx
+++ b/web/src/pages/studio/Producer.tsx
@@ -123,8 +123,8 @@ const ProducerPage = () => {
   }, []);
 
   // Invalidates any in-flight connection query and drops its visible results,
-  // shared by every scope change (instance / topic) so a slow response can 
never
-  // repopulate results that belong to a different scope.
+  // shared by every scope change (instance / topic / producer group) so a slow
+  // response can never repopulate results that belong to a different scope.
   const resetConnectionQuery = () => {
     queryRequestIdRef.current += 1;
     queryInFlightRef.current = null;
@@ -375,6 +375,12 @@ const ProducerPage = () => {
               onSearch={(value) => {
                 void loadProducerGroups(value);
               }}
+              onChange={() => {
+                // Editing the optional group filter is a criteria change like 
a topic edit:
+                // an in-flight query belongs to the group it was started 
with, and its rows
+                // must not survive the edit or land underneath the new 
criteria.
+                resetConnectionQuery();
+              }}
               filterOption={(inputValue, option) =>
                 option?.value.toLowerCase().includes(inputValue.toLowerCase()) 
?? false
               }
diff --git a/web/src/pages/studio/__tests__/Producer.test.tsx 
b/web/src/pages/studio/__tests__/Producer.test.tsx
index b4b33736d..eccb2a665 100644
--- a/web/src/pages/studio/__tests__/Producer.test.tsx
+++ b/web/src/pages/studio/__tests__/Producer.test.tsx
@@ -636,6 +636,109 @@ describe('ProducerPage', () => {
     expect(await screen.findByText('payment-producer-1')).toBeInTheDocument();
   });
 
+  it('clears stale connection results when the producer group changes', async 
() => {
+    const user = userEvent.setup();
+    vi.mocked(queryProducerConnection).mockResolvedValue(
+      producerResult([
+        {
+          clientId: 'producer-1',
+          clientAddr: '192.168.1.10',
+          topic: 'order-events',
+          producerGroup: 'pg-order',
+          language: 'JAVA',
+          versionDesc: '5.1.0',
+        },
+      ]),
+    );
+    renderWithProviders(<ProducerPage />);
+
+    await waitFor(() => expect(fetchTopicList).toHaveBeenCalledTimes(1));
+    const [, topicSelect, groupInput] = screen.getAllByRole('combobox');
+    fireEvent.mouseDown(topicSelect.parentElement!);
+    await user.click(
+      await screen.findByText('order-events', { selector: 
'.ant-select-item-option-content' }),
+    );
+    await user.type(groupInput, 'pg-order');
+    await user.click(screen.getByRole('button', { name: /搜索/ }));
+
+    expect(await screen.findByText('producer-1')).toBeInTheDocument();
+    expect(await screen.findByText('生产者连接健康')).toBeInTheDocument();
+
+    // Editing the group after a completed query is a criteria change like a 
topic edit:
+    // the rows on screen no longer describe what the form would search for.
+    await user.type(groupInput, '-v2');
+
+    await waitFor(() => {
+      expect(screen.queryByText('producer-1')).not.toBeInTheDocument();
+    });
+    expect(screen.queryByText('生产者连接健康')).not.toBeInTheDocument();
+    expect(screen.queryByText('就绪')).not.toBeInTheDocument();
+  });
+
+  it('discards a slow connection response after the producer group changes', 
async () => {
+    const user = userEvent.setup();
+    let resolveGroupAQuery: ((value: ProducerConnectionResult) => void) | 
undefined;
+    vi.mocked(queryProducerConnection)
+      .mockImplementationOnce(
+        () =>
+          new Promise((resolve) => {
+            resolveGroupAQuery = resolve;
+          }),
+      )
+      .mockResolvedValueOnce(
+        producerResult([
+          {
+            clientId: 'payment-producer-1',
+            clientAddr: '192.168.1.20',
+            topic: 'order-events',
+            producerGroup: 'pg-payment',
+            language: 'JAVA',
+            versionDesc: '5.1.0',
+          },
+        ]),
+      );
+    renderWithProviders(<ProducerPage />);
+
+    await waitFor(() => expect(fetchTopicList).toHaveBeenCalledTimes(1));
+    const [, topicSelect, groupInput] = screen.getAllByRole('combobox');
+    fireEvent.mouseDown(topicSelect.parentElement!);
+    await user.click(
+      await screen.findByText('order-events', { selector: 
'.ant-select-item-option-content' }),
+    );
+    await user.type(groupInput, 'pg-order');
+    await user.click(screen.getByRole('button', { name: /搜索/ }));
+    await waitFor(() => 
expect(queryProducerConnection).toHaveBeenCalledTimes(1));
+
+    // While the pg-order query is still pending, edit the group.
+    await user.type(groupInput, '2');
+
+    resolveGroupAQuery?.(
+      producerResult([
+        {
+          clientId: 'stale-producer',
+          clientAddr: '192.168.1.10',
+          language: 'JAVA',
+          versionDesc: '5.1.0',
+        },
+      ]),
+    );
+    await waitFor(() => {
+      expect(screen.queryByText('stale-producer')).not.toBeInTheDocument();
+    });
+    expect(screen.queryByText('生产者连接健康')).not.toBeInTheDocument();
+
+    // The group edit must also release the in-flight slot so a fresh query 
runs.
+    await user.click(screen.getByRole('button', { name: /搜索/ }));
+    await waitFor(() => {
+      expect(queryProducerConnection).toHaveBeenLastCalledWith(
+        'instance-1',
+        'order-events',
+        'pg-order2',
+      );
+    });
+    expect(await screen.findByText('payment-producer-1')).toBeInTheDocument();
+  });
+
   it('does not discover producer groups before a topic is selected', async () 
=> {
     const user = userEvent.setup();
     renderWithProviders(<ProducerPage />);

Reply via email to