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 457fa7baa fix(web): sequence audit, client connection, cluster
inventory and DLQ group requests (#2592)
457fa7baa is described below
commit 457fa7baa62097bb7895ca6384ef895a554d5eba
Author: xdz997 <[email protected]>
AuthorDate: Thu Aug 27 14:18:09 2026 +0800
fix(web): sequence audit, client connection, cluster inventory and DLQ
group requests (#2592)
* fix: sequence audit log filter requests
* fix: sequence client connection requests
* fix: sequence cluster inventory requests
* fix: sequence DLQ group requests
---
.../pages/cluster/__tests__/ClientsPage.test.tsx | 69 ++++++++++++++++-
.../pages/cluster/__tests__/ClusterPage.test.tsx | 31 ++++++++
web/src/pages/cluster/clients.tsx | 44 ++++++-----
web/src/pages/cluster/index.tsx | 90 +++++++++++-----------
web/src/pages/instance/__tests__/DLQPage.test.tsx | 25 ++++++
web/src/pages/instance/dlq.tsx | 24 +++---
web/src/pages/ops/__tests__/AuditPage.test.tsx | 47 ++++++++++-
web/src/pages/ops/audit.tsx | 75 +++++++++++-------
8 files changed, 299 insertions(+), 106 deletions(-)
diff --git a/web/src/pages/cluster/__tests__/ClientsPage.test.tsx
b/web/src/pages/cluster/__tests__/ClientsPage.test.tsx
index 8573facb5..e8b5bae57 100644
--- a/web/src/pages/cluster/__tests__/ClientsPage.test.tsx
+++ b/web/src/pages/cluster/__tests__/ClientsPage.test.tsx
@@ -16,7 +16,7 @@
*/
import { App } from 'antd';
-import { render, screen, waitFor, within } from '@testing-library/react';
+import { act, render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type React from 'react';
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from
'vitest';
@@ -139,6 +139,16 @@ const renderWithProviders = (ui: React.ReactElement) =>
</App>,
);
+const deferred = <T,>() => {
+ let resolve!: (value: T) => void;
+ let reject!: (reason?: unknown) => void;
+ const promise = new Promise<T>((resolvePromise, rejectPromise) => {
+ resolve = resolvePromise;
+ reject = rejectPromise;
+ });
+ return { promise, resolve, reject };
+};
+
describe('Clients page', () => {
it('returns to the first page when the connection search changes', async ()
=> {
const pagedConnections = Array.from({ length: 21 }, (_, index) => ({
@@ -392,6 +402,63 @@ describe('Clients page', () => {
expect(within(screen.getByTestId('connection-total')).getByText('0')).toBeInTheDocument();
});
+ it('ignores a stale connection response after switching nameservers', async
() => {
+ const user = userEvent.setup();
+ const stale = deferred<ClientConnection[]>();
+ const latest = deferred<ClientConnection[]>();
+ vi.mocked(connectionsService.listConnections)
+ .mockImplementationOnce(() => stale.promise)
+ .mockImplementationOnce(() => latest.promise);
+
+ renderWithProviders(<ClientsPage />);
+
+ await user.click(screen.getByRole('combobox', { name: 'NameServer' }));
+ await user.click(
+ await screen.findByText('rocketmq2 (namesrv-2:9876)', {
+ selector: '.ant-select-item-option-content',
+ }),
+ );
+
+ await waitFor(() =>
+ expect(connectionsService.listConnections).toHaveBeenLastCalledWith({
+ namesrvAddr: 'namesrv-2:9876',
+ }),
+ );
+
+ await act(async () => {
+ latest.resolve(connections);
+ stale.resolve([{ ...connection, clientId: '[email protected]:49160'
}]);
+ await Promise.resolve();
+ await Promise.resolve();
+ });
+
+
expect(screen.queryByText('[email protected]:49160')).not.toBeInTheDocument();
+
expect(within(screen.getByTestId('connection-total')).getByText('3')).toBeInTheDocument();
+ });
+
+ it('ignores a stale registry response after a retry', async () => {
+ const user = userEvent.setup();
+ const stale = deferred<ClusterInfo[]>();
+ vi.mocked(clusterService.listRegistryClusters)
+ .mockRejectedValueOnce(new Error('Unable to load registry clusters'))
+ .mockImplementationOnce(() => stale.promise);
+
+ renderWithProviders(<ClientsPage />);
+
+ expect(await screen.findByText('Unable to load registry
clusters')).toBeInTheDocument();
+ await user.click(screen.getByRole('button', { name: /重\s*试/ }));
+ await waitFor(() =>
+ expect(clusterService.listRegistryClusters).toHaveBeenNthCalledWith(2),
+ );
+
+ await act(async () => {
+ stale.resolve([]);
+ });
+
+ expect(screen.queryByText('Unable to load registry
clusters')).not.toBeInTheDocument();
+ expect(connectionsService.listConnections).toHaveBeenCalledTimes(0);
+ });
+
it('surfaces registry discovery failures and allows retrying', async () => {
vi.mocked(clusterService.listRegistryClusters)
.mockRejectedValueOnce(new Error('Unable to load registry clusters'))
diff --git a/web/src/pages/cluster/__tests__/ClusterPage.test.tsx
b/web/src/pages/cluster/__tests__/ClusterPage.test.tsx
index 12037bf15..be42cd09d 100644
--- a/web/src/pages/cluster/__tests__/ClusterPage.test.tsx
+++ b/web/src/pages/cluster/__tests__/ClusterPage.test.tsx
@@ -757,4 +757,35 @@ describe('Cluster page', () => {
expect(clusterServiceMocks.listClusters).toHaveBeenCalledTimes(1);
});
+
+ it('ignores stale registry-cluster and nameserver responses', async () => {
+ const staleClusters = deferred<ClusterInfo[]>();
+ const latestClusters = deferred<ClusterInfo[]>();
+ clusterServiceMocks.listRegistryClusters
+ .mockImplementationOnce(() => staleClusters.promise)
+ .mockImplementationOnce(() => latestClusters.promise);
+
+ renderWithProviders(<ClusterPage />);
+ await flushPromises();
+ fireEvent.click(screen.getByRole('button', { name: '刷新' }));
+ await flushPromises();
+
+ await act(async () => {
+ staleClusters.resolve([buildCluster({ connections: 501 })]);
+ await staleClusters.promise;
+ await Promise.resolve();
+ });
+
+ expect(screen.queryByText('501')).not.toBeInTheDocument();
+
+ fireEvent.click(screen.getByRole('tab', { name: /Proxy 管理/ }));
+
+ await act(async () => {
+ latestClusters.resolve([buildCluster({ connections: 502 })]);
+ await latestClusters.promise;
+ await Promise.resolve();
+ });
+
+ expect(screen.getByText('502')).toBeInTheDocument();
+ });
});
diff --git a/web/src/pages/cluster/clients.tsx
b/web/src/pages/cluster/clients.tsx
index 24700fcef..d696550de 100644
--- a/web/src/pages/cluster/clients.tsx
+++ b/web/src/pages/cluster/clients.tsx
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo, useRef, useState } from 'react';
import {
Alert,
Button,
@@ -137,6 +137,8 @@ const ClientsPage = () => {
const [columnFilters, setColumnFilters] = useState<ClientTableFilters>({});
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
+ const registryRequestRef = useRef(0);
+ const connectionRequestRef = useRef(0);
const selectedCluster = registryClusters.find((cluster) => cluster.endpoint
=== selectedEndpoint);
@@ -150,6 +152,7 @@ const ClientsPage = () => {
);
const handleNameserverChange = (endpoint: string) => {
+ connectionRequestRef.current += 1;
setCurrentPage(1);
setSelectedEndpoint(endpoint);
setConnections([]);
@@ -160,11 +163,11 @@ const ClientsPage = () => {
};
useEffect(() => {
- let cancelled = false;
+ const requestId = ++registryRequestRef.current;
void listRegistryClusters()
.then((nextClusters) => {
- if (cancelled) return;
+ if (registryRequestRef.current !== requestId) return;
setRegistryClusters(nextClusters);
setSelectedEndpoint((current) => {
if (current && nextClusters.some((cluster) => cluster.endpoint ===
current)) {
@@ -175,38 +178,35 @@ const ClientsPage = () => {
setLoadError(null);
})
.catch((error) => {
- if (cancelled) return;
+ if (registryRequestRef.current !== requestId) return;
setRegistryClusters([]);
setSelectedEndpoint(undefined);
setConnections([]);
setLoadError(getLoadErrorMessage(error));
})
.finally(() => {
- if (!cancelled) setLoading(false);
+ if (registryRequestRef.current === requestId) setLoading(false);
});
-
- return () => {
- cancelled = true;
- };
}, [registryLoadKey]);
useEffect(() => {
- let cancelled = false;
+ const requestId = ++connectionRequestRef.current;
if (!selectedEndpoint || !selectedCluster) {
- return () => {
- cancelled = true;
- };
+ return;
}
+ void Promise.resolve().then(() => {
+ if (connectionRequestRef.current === requestId) setLoading(true);
+ });
void listConnections({ namesrvAddr: selectedEndpoint })
.then((nextConnections) => {
- if (!cancelled) {
+ if (connectionRequestRef.current === requestId) {
setConnections(nextConnections);
setLoadError(null);
}
})
.catch((error) => {
- if (!cancelled) {
+ if (connectionRequestRef.current === requestId) {
setConnections([]);
setClusterFilter('ALL');
setSelectedConnection(null);
@@ -214,14 +214,18 @@ const ClientsPage = () => {
}
})
.finally(() => {
- if (!cancelled) setLoading(false);
+ if (connectionRequestRef.current === requestId) setLoading(false);
});
-
- return () => {
- cancelled = true;
- };
}, [connectionLoadKey, selectedEndpoint, selectedCluster]);
+ useEffect(
+ () => () => {
+ registryRequestRef.current += 1;
+ connectionRequestRef.current += 1;
+ },
+ [],
+ );
+
/* ─── Cluster options using nsClusterName ─── */
const clusterOptions = useMemo(() => {
const clusterNames = [
diff --git a/web/src/pages/cluster/index.tsx b/web/src/pages/cluster/index.tsx
index 254882f4a..58051a758 100644
--- a/web/src/pages/cluster/index.tsx
+++ b/web/src/pages/cluster/index.tsx
@@ -129,77 +129,75 @@ const ClusterPage = () => {
const [selectedProxy, setSelectedProxy] = useState<ProxyDetail | null>(null);
const [configForm] = Form.useForm();
- const loadNsRegistry = useCallback(async () => {
- try {
- setNsRegistry(await listNameserverRegistry());
- } catch {
- setNsRegistry([]);
- }
- }, []);
-
- useEffect(() => {
- let active = true;
- listNameserverRegistry()
- .then((entries) => {
- if (active) setNsRegistry(entries);
- })
- .catch(() => {
- if (active) setNsRegistry([]);
- });
- return () => {
- active = false;
- };
- }, []);
-
const [k8sIdOptions, setK8sIdOptions] = useState<string[]>([]);
const [registryClusters, setRegistryClusters] = useState<ClusterInfo[]>([]);
const [registryLoading, setRegistryLoading] = useState(true);
+ const nsRegistryRequestRef = useRef(0);
+ const registryClustersRequestRef = useRef(0);
+ const k8sCertsRequestRef = useRef(0);
const loadRegistryClusters = useCallback(async () => {
- setRegistryLoading(true);
+ const requestId = ++registryClustersRequestRef.current;
+ void Promise.resolve().then(() => {
+ if (registryClustersRequestRef.current === requestId)
setRegistryLoading(true);
+ });
try {
- setRegistryClusters(await listRegistryClusters());
+ const nextClusters = await listRegistryClusters();
+ if (registryClustersRequestRef.current === requestId) {
+ setRegistryClusters(nextClusters);
+ }
} catch {
- setRegistryClusters([]);
+ if (registryClustersRequestRef.current === requestId) {
+ setRegistryClusters([]);
+ }
} finally {
- setRegistryLoading(false);
+ if (registryClustersRequestRef.current === requestId) {
+ setRegistryLoading(false);
+ }
}
}, []);
useEffect(() => {
- let active = true;
- listRegistryClusters()
- .then((next) => {
- if (active) setRegistryClusters(next);
- })
- .catch(() => {
- if (active) setRegistryClusters([]);
- })
- .finally(() => {
- if (active) setRegistryLoading(false);
- });
- return () => {
- active = false;
- };
+ void Promise.resolve().then(loadRegistryClusters);
+ }, [loadRegistryClusters]);
+
+ const loadNsRegistry = useCallback(async () => {
+ const requestId = ++nsRegistryRequestRef.current;
+ try {
+ const entries = await listNameserverRegistry();
+ if (nsRegistryRequestRef.current === requestId) setNsRegistry(entries);
+ } catch {
+ if (nsRegistryRequestRef.current === requestId) setNsRegistry([]);
+ }
}, []);
useEffect(() => {
- let active = true;
+ void Promise.resolve().then(loadNsRegistry);
+ }, [loadNsRegistry]);
+
+ useEffect(() => {
+ const requestId = ++k8sCertsRequestRef.current;
listK8sCerts()
.then((certs) => {
- if (active) {
+ if (k8sCertsRequestRef.current === requestId) {
setK8sIdOptions([...new Set(certs.map((cert) =>
cert.k8sId).filter(Boolean))]);
}
})
.catch(() => {
- if (active) setK8sIdOptions([]);
+ if (k8sCertsRequestRef.current === requestId) setK8sIdOptions([]);
});
- return () => {
- active = false;
- };
}, []);
+ useEffect(
+ () => () => {
+ nsRegistryRequestRef.current += 1;
+ registryClustersRequestRef.current += 1;
+ k8sCertsRequestRef.current += 1;
+ },
+ [],
+ );
+
const [nsCreateModalOpen, setNsCreateModalOpen] = useState(false);
const [nsModalMode, setNsModalMode] = useState<'create' | 'edit'>('create');
const [nsEditId, setNsEditId] = useState<number | null>(null);
diff --git a/web/src/pages/instance/__tests__/DLQPage.test.tsx
b/web/src/pages/instance/__tests__/DLQPage.test.tsx
index 55860b563..df86adf25 100644
--- a/web/src/pages/instance/__tests__/DLQPage.test.tsx
+++ b/web/src/pages/instance/__tests__/DLQPage.test.tsx
@@ -487,4 +487,29 @@ describe('DLQ page', () => {
expect(within(retryDialog as
HTMLElement).getByText('-cg-"payment"')).toBeInTheDocument();
expect(messageService.listDLQGroups).toHaveBeenCalledTimes(2);
});
+
+ it('ignores a stale group response after changing instances', async () => {
+ let resolveFirstInstance!: (page: DLQGroupPage) => void;
+ vi.mocked(messageService.listDLQGroups)
+ .mockImplementationOnce(
+ () =>
+ new Promise<DLQGroupPage>((resolve) => {
+ resolveFirstInstance = resolve;
+ }),
+ )
+ .mockResolvedValueOnce(pageOf([secondDlqGroup]));
+ const user = userEvent.setup();
+ renderWithProviders(<DLQPage />);
+
+ await user.click(screen.getAllByRole('combobox')[0]);
+ await user.click(
+ await screen.findByText('instance-2', { selector:
'.ant-select-item-option-content' }),
+ );
+ expect(await screen.findByText('-cg-"payment"')).toBeInTheDocument();
+
+ await act(async () => resolveFirstInstance(pageOf([dlqGroup])));
+
+ expect(screen.queryByText('cg-order')).not.toBeInTheDocument();
+ expect(screen.getByText('-cg-"payment"')).toBeInTheDocument();
+ });
});
diff --git a/web/src/pages/instance/dlq.tsx b/web/src/pages/instance/dlq.tsx
index 919e8924e..5cb14544e 100644
--- a/web/src/pages/instance/dlq.tsx
+++ b/web/src/pages/instance/dlq.tsx
@@ -142,6 +142,7 @@ const DLQPage = () => {
const [detailError, setDetailError] = useState<string | null>(null);
const detailRequestIdRef = useRef(0);
const retryRequestIdRef = useRef(0);
+ const groupRequestIdRef = useRef(0);
useEffect(
() => () => {
@@ -175,16 +176,14 @@ const DLQPage = () => {
}
useEffect(() => {
- let cancelled = false;
+ const requestId = ++groupRequestIdRef.current;
if (!selectedInstanceId) {
void Promise.resolve().then(() => {
- if (cancelled) return;
+ if (groupRequestIdRef.current !== requestId) return;
setLoading(false);
});
- return () => {
- cancelled = true;
- };
+ return;
}
// Clear `loading` inside the same callback as the data updates so rows and
@@ -192,7 +191,7 @@ const DLQPage = () => {
// visible for a render while the spin overlay still blocks pointer events.
void listDLQGroups(selectedInstanceId, search || undefined, page, pageSize)
.then((result) => {
- if (!cancelled) {
+ if (groupRequestIdRef.current === requestId) {
setGroups(result.items);
setTotal(result.total);
setLoadError(null);
@@ -206,17 +205,20 @@ const DLQPage = () => {
}
})
.catch((error) => {
- if (!cancelled) {
+ if (groupRequestIdRef.current === requestId) {
setLoadError(getErrorMessage(error, DEFAULT_LOAD_ERROR));
setLoading(false);
}
});
-
- return () => {
- cancelled = true;
- };
}, [refreshKey, selectedInstanceId, search, page, pageSize]);
+ useEffect(
+ () => () => {
+ groupRequestIdRef.current += 1;
+ },
+ [],
+ );
+
const selectedGroups = useMemo(() => {
const selected = new Set(selectedGroupNames);
return groups.filter((group) => selected.has(group.groupName));
diff --git a/web/src/pages/ops/__tests__/AuditPage.test.tsx
b/web/src/pages/ops/__tests__/AuditPage.test.tsx
index d1600138d..65489e0a7 100644
--- a/web/src/pages/ops/__tests__/AuditPage.test.tsx
+++ b/web/src/pages/ops/__tests__/AuditPage.test.tsx
@@ -16,7 +16,7 @@
*/
import { App } from 'antd';
-import { render, screen, waitFor } from '@testing-library/react';
+import { act, render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import type React from 'react';
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from
'vitest';
@@ -38,6 +38,14 @@ const renderWithProviders = (ui: React.ReactElement) =>
</App>,
);
+const deferred = <T,>() => {
+ let resolve!: (value: T) => void;
+ const promise = new Promise<T>((resolvePromise) => {
+ resolve = resolvePromise;
+ });
+ return { promise, resolve };
+};
+
describe('Audit page', () => {
let createObjectURL: ReturnType<typeof vi.fn>;
let revokeObjectURL: ReturnType<typeof vi.fn>;
@@ -112,6 +120,11 @@ describe('Audit page', () => {
expect(await screen.findByText('topic-a')).toBeInTheDocument();
await user.type(screen.getByPlaceholderText('搜索操作人或操作对象'), 'topic-a');
+ await waitFor(() =>
+ expect(opsService.listAuditRecords).toHaveBeenLastCalledWith(
+ expect.objectContaining({ search: 'topic-a' }),
+ ),
+ );
await user.click(screen.getByRole('button', { name: /导出/ }));
await waitFor(() =>
@@ -203,6 +216,38 @@ describe('Audit page', () => {
expect(container.querySelector('.ant-spin-spinning')).not.toBeNull();
});
+ it('ignores stale filter-option responses after cleanup refreshes', async ()
=> {
+ const user = userEvent.setup();
+ const staleOptions =
+ deferred<Awaited<ReturnType<typeof opsService.getAuditFilterOptions>>>();
+ vi.mocked(opsService.getAuditFilterOptions)
+ .mockImplementationOnce(() => new Promise(() => {}))
+ .mockImplementationOnce(() => staleOptions.promise);
+ vi.mocked(opsService.cleanupAuditLogs).mockResolvedValue(3);
+
+ renderWithProviders(<AuditPage />);
+
+ expect(await screen.findByText('topic-a')).toBeInTheDocument();
+ await user.click(screen.getByRole('button', { name: /清理日志/ }));
+ await user.click(await screen.findByRole('button', { name: /确认清理/ }));
+
+ await waitFor(() =>
+ expect(opsService.getAuditFilterOptions).toHaveBeenNthCalledWith(2),
+ );
+
+ await act(async () => {
+ staleOptions.resolve({
+ operationTypes: ['STALE_OPERATION'],
+ resourceTypes: [],
+ clusterIds: [],
+ results: [],
+ });
+ });
+
+ await user.click(screen.getByRole('combobox', { name: '操作类型' }));
+ expect(await screen.findByText('STALE OPERATION')).toBeInTheDocument();
+ });
+
it('still loads audit records when filter options cannot be loaded', async
() => {
vi.mocked(opsService.getAuditFilterOptions).mockRejectedValueOnce(new
Error('unavailable'));
diff --git a/web/src/pages/ops/audit.tsx b/web/src/pages/ops/audit.tsx
index 0884db083..98ca6cca8 100644
--- a/web/src/pages/ops/audit.tsx
+++ b/web/src/pages/ops/audit.tsx
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useRef, useState } from 'react';
import {
Card,
Table,
@@ -100,21 +100,21 @@ const AuditPage: React.FC = () => {
const [cleanupModalOpen, setCleanupModalOpen] = useState(false);
const [cleanupDays, setCleanupDays] = useState(30);
const [exporting, setExporting] = useState(false);
+ const recordsRequestRef = useRef(0);
+ const filterOptionsRequestRef = useRef(0);
useEffect(() => {
- let cancelled = false;
+ const requestId = ++filterOptionsRequestRef.current;
void getAuditFilterOptions()
.then((options) => {
- if (!cancelled) setFilterOptions(options);
+ if (filterOptionsRequestRef.current === requestId)
setFilterOptions(options);
})
.catch(() => {
- if (!cancelled) setFilterOptions(emptyFilterOptions);
+ if (filterOptionsRequestRef.current === requestId) {
+ setFilterOptions(emptyFilterOptions);
+ }
});
-
- return () => {
- cancelled = true;
- };
}, [refreshKey]);
// Debounce free-text search so the record list is not re-fetched on every
@@ -125,9 +125,9 @@ const AuditPage: React.FC = () => {
}, [searchText]);
useEffect(() => {
- let cancelled = false;
+ const requestId = ++recordsRequestRef.current;
void Promise.resolve().then(() => {
- if (!cancelled) setLoading(true);
+ if (recordsRequestRef.current === requestId) setLoading(true);
});
void listAuditRecords({
@@ -143,20 +143,22 @@ const AuditPage: React.FC = () => {
),
})
.then((result) => {
- if (cancelled) return;
+ if (recordsRequestRef.current !== requestId) return;
setRecords(result.items);
setTotal(result.total);
+ if (result.items.length === 0 && result.total > 0 && page > 1) {
+ setPage(Math.max(1, Math.ceil(result.total / pageSize)));
+ return;
+ }
})
.catch(() => {
- if (!cancelled) message.error('审计日志加载失败,请稍后重试');
+ if (recordsRequestRef.current === requestId) {
+ message.error('审计日志加载失败,请稍后重试');
+ }
})
.finally(() => {
- if (!cancelled) setLoading(false);
+ if (recordsRequestRef.current === requestId) setLoading(false);
});
-
- return () => {
- cancelled = true;
- };
}, [
page,
pageSize,
@@ -169,6 +171,34 @@ const AuditPage: React.FC = () => {
refreshKey,
]);
+ useEffect(
+ () => () => {
+ recordsRequestRef.current += 1;
+ filterOptionsRequestRef.current += 1;
+ },
+ [],
+ );
+
+ const activeFilter = useMemo(
+ () =>
+ buildAuditFilter(
+ debouncedSearchText,
+ selectedType,
+ selectedResourceType,
+ selectedClusterId,
+ dateRange,
+ resultFilter,
+ ),
+ [
+ debouncedSearchText,
+ selectedType,
+ selectedResourceType,
+ selectedClusterId,
+ dateRange,
+ resultFilter,
+ ],
+ );
+
const { Text } = Typography;
const handleCleanup = async () => {
@@ -186,16 +216,7 @@ const AuditPage: React.FC = () => {
const handleExport = async () => {
setExporting(true);
try {
- const csv = await exportAuditLogs(
- buildAuditFilter(
- searchText,
- selectedType,
- selectedResourceType,
- selectedClusterId,
- dateRange,
- resultFilter,
- ),
- );
+ const csv = await exportAuditLogs(activeFilter);
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
downloadBlob(blob,
`rocketmq-audit-logs-${dayjs().format('YYYY-MM-DD')}.csv`);
} catch {