feat: add auto-refresh toggle wired to all polling queries
Upgrade @cameleer/design-system to ^0.1.3 which adds LIVE/PAUSED toggle to TopBar backed by autoRefresh state in GlobalFilterProvider. Add useRefreshInterval() hook that returns the polling interval when auto-refresh is on, or false when paused. Wire it into all query hooks that use refetchInterval (executions, catalog, agents, metrics, admin database/opensearch). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { adminFetch } from './admin-api';
|
||||
import { useRefreshInterval } from '../use-refresh-interval';
|
||||
|
||||
// ── Types ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -38,34 +39,38 @@ export interface ActiveQuery {
|
||||
// ── Query Hooks ────────────────────────────────────────────────────────
|
||||
|
||||
export function useDatabaseStatus() {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'database', 'status'],
|
||||
queryFn: () => adminFetch<DatabaseStatus>('/database/status'),
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useConnectionPool() {
|
||||
const refetchInterval = useRefreshInterval(10_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'database', 'pool'],
|
||||
queryFn: () => adminFetch<PoolStats>('/database/pool'),
|
||||
refetchInterval: 10_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useDatabaseTables() {
|
||||
const refetchInterval = useRefreshInterval(60_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'database', 'tables'],
|
||||
queryFn: () => adminFetch<TableInfo[]>('/database/tables'),
|
||||
refetchInterval: 60_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useActiveQueries() {
|
||||
const refetchInterval = useRefreshInterval(5_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'database', 'queries'],
|
||||
queryFn: () => adminFetch<ActiveQuery[]>('/database/queries'),
|
||||
refetchInterval: 5_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { adminFetch } from './admin-api';
|
||||
import { useRefreshInterval } from '../use-refresh-interval';
|
||||
|
||||
// ── Types ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -53,18 +54,20 @@ export interface PerformanceStats {
|
||||
// ── Query Hooks ────────────────────────────────────────────────────────
|
||||
|
||||
export function useOpenSearchStatus() {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'opensearch', 'status'],
|
||||
queryFn: () => adminFetch<OpenSearchStatus>('/opensearch/status'),
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function usePipelineStats() {
|
||||
const refetchInterval = useRefreshInterval(10_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'opensearch', 'pipeline'],
|
||||
queryFn: () => adminFetch<PipelineStats>('/opensearch/pipeline'),
|
||||
refetchInterval: 10_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -83,10 +86,11 @@ export function useOpenSearchIndices(page = 0, size = 20, search = '') {
|
||||
}
|
||||
|
||||
export function useOpenSearchPerformance() {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['admin', 'opensearch', 'performance'],
|
||||
queryFn: () => adminFetch<PerformanceStats>('/opensearch/performance'),
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { config } from '../../config';
|
||||
import { useAuthStore } from '../../auth/auth-store';
|
||||
import { useRefreshInterval } from './use-refresh-interval';
|
||||
|
||||
export function useAgentMetrics(agentId: string | null, names: string[], buckets = 60) {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['agent-metrics', agentId, names.join(','), buckets],
|
||||
queryFn: async () => {
|
||||
@@ -21,6 +23,6 @@ export function useAgentMetrics(agentId: string | null, names: string[], buckets
|
||||
return res.json() as Promise<{ metrics: Record<string, Array<{ time: string; value: number }>> }>;
|
||||
},
|
||||
enabled: !!agentId && names.length > 0,
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { api } from '../client';
|
||||
import { config } from '../../config';
|
||||
import { useAuthStore } from '../../auth/auth-store';
|
||||
import { useRefreshInterval } from './use-refresh-interval';
|
||||
|
||||
export function useAgents(status?: string, application?: string) {
|
||||
const refetchInterval = useRefreshInterval(10_000);
|
||||
return useQuery({
|
||||
queryKey: ['agents', status, application],
|
||||
queryFn: async () => {
|
||||
@@ -13,11 +15,12 @@ export function useAgents(status?: string, application?: string) {
|
||||
if (error) throw new Error('Failed to load agents');
|
||||
return data!;
|
||||
},
|
||||
refetchInterval: 10_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useAgentEvents(appId?: string, agentId?: string, limit = 50) {
|
||||
const refetchInterval = useRefreshInterval(15_000);
|
||||
return useQuery({
|
||||
queryKey: ['agents', 'events', appId, agentId, limit],
|
||||
queryFn: async () => {
|
||||
@@ -35,6 +38,6 @@ export function useAgentEvents(appId?: string, agentId?: string, limit = 50) {
|
||||
if (!res.ok) throw new Error('Failed to load agent events');
|
||||
return res.json();
|
||||
},
|
||||
refetchInterval: 15_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { config } from '../../config';
|
||||
import { useAuthStore } from '../../auth/auth-store';
|
||||
import { useRefreshInterval } from './use-refresh-interval';
|
||||
|
||||
export function useRouteCatalog() {
|
||||
const refetchInterval = useRefreshInterval(15_000);
|
||||
return useQuery({
|
||||
queryKey: ['routes', 'catalog'],
|
||||
queryFn: async () => {
|
||||
@@ -16,11 +18,12 @@ export function useRouteCatalog() {
|
||||
if (!res.ok) throw new Error('Failed to load route catalog');
|
||||
return res.json();
|
||||
},
|
||||
refetchInterval: 15_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useRouteMetrics(from?: string, to?: string, appId?: string) {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['routes', 'metrics', from, to, appId],
|
||||
queryFn: async () => {
|
||||
@@ -38,6 +41,6 @@ export function useRouteMetrics(from?: string, to?: string, appId?: string) {
|
||||
if (!res.ok) throw new Error('Failed to load route metrics');
|
||||
return res.json();
|
||||
},
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { api } from '../client';
|
||||
import type { SearchRequest } from '../types';
|
||||
import { useRefreshInterval } from './use-refresh-interval';
|
||||
|
||||
export function useExecutionStats(
|
||||
timeFrom: string | undefined,
|
||||
@@ -8,6 +9,7 @@ export function useExecutionStats(
|
||||
routeId?: string,
|
||||
application?: string,
|
||||
) {
|
||||
const refetchInterval = useRefreshInterval(10_000);
|
||||
return useQuery({
|
||||
queryKey: ['executions', 'stats', timeFrom, timeTo, routeId, application],
|
||||
queryFn: async () => {
|
||||
@@ -26,11 +28,12 @@ export function useExecutionStats(
|
||||
},
|
||||
enabled: !!timeFrom,
|
||||
placeholderData: (prev) => prev,
|
||||
refetchInterval: 10_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
export function useSearchExecutions(filters: SearchRequest, live = false) {
|
||||
const refetchInterval = useRefreshInterval(5_000);
|
||||
return useQuery({
|
||||
queryKey: ['executions', 'search', filters],
|
||||
queryFn: async () => {
|
||||
@@ -41,7 +44,7 @@ export function useSearchExecutions(filters: SearchRequest, live = false) {
|
||||
return data!;
|
||||
},
|
||||
placeholderData: (prev) => prev,
|
||||
refetchInterval: live ? 5_000 : false,
|
||||
refetchInterval: live ? refetchInterval : false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,6 +54,7 @@ export function useStatsTimeseries(
|
||||
routeId?: string,
|
||||
application?: string,
|
||||
) {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['executions', 'timeseries', timeFrom, timeTo, routeId, application],
|
||||
queryFn: async () => {
|
||||
@@ -70,7 +74,7 @@ export function useStatsTimeseries(
|
||||
},
|
||||
enabled: !!timeFrom,
|
||||
placeholderData: (prev) => prev,
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { config } from '../../config';
|
||||
import { useAuthStore } from '../../auth/auth-store';
|
||||
import { useRefreshInterval } from './use-refresh-interval';
|
||||
|
||||
export function useProcessorMetrics(routeId: string | null, appId?: string) {
|
||||
const refetchInterval = useRefreshInterval(30_000);
|
||||
return useQuery({
|
||||
queryKey: ['processor-metrics', routeId, appId],
|
||||
queryFn: async () => {
|
||||
@@ -20,6 +22,6 @@ export function useProcessorMetrics(routeId: string | null, appId?: string) {
|
||||
return res.json();
|
||||
},
|
||||
enabled: !!routeId,
|
||||
refetchInterval: 30_000,
|
||||
refetchInterval,
|
||||
});
|
||||
}
|
||||
|
||||
10
ui/src/api/queries/use-refresh-interval.ts
Normal file
10
ui/src/api/queries/use-refresh-interval.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { useGlobalFilters } from '@cameleer/design-system';
|
||||
|
||||
/**
|
||||
* Returns the given interval when auto-refresh is enabled, or `false` when paused.
|
||||
* Use as `refetchInterval` in React Query hooks.
|
||||
*/
|
||||
export function useRefreshInterval(intervalMs: number): number | false {
|
||||
const { autoRefresh } = useGlobalFilters();
|
||||
return autoRefresh ? intervalMs : false;
|
||||
}
|
||||
Reference in New Issue
Block a user