milestone 30: overview as a dashboard, explicit health contract, period aggregations
This commit is contained in:
+29
-17
@@ -24,13 +24,15 @@ export const queryKeys = {
|
||||
version: ["version"] as const,
|
||||
stats: (period: Period) => ["stats", period] as const,
|
||||
timeseries: (period: Period) => ["stats", "timeseries", period] as const,
|
||||
statsTypes: (period: Period) => ["stats", "types", period] as const,
|
||||
statsRoutes: (period: Period) => ["stats", "routes", period] as const,
|
||||
statsClients: (period: Period) => ["stats", "clients", period] as const,
|
||||
queriesInfinite: (filter: QueriesFilter) => ["queries", "infinite", filter] as const,
|
||||
queryDetail: (id: number) => ["queries", "detail", id] as const,
|
||||
diagnosticsInfinite: (filter: DiagnosticsFilter) => ["diagnostics", "infinite", filter] as const,
|
||||
diagnostic: (id: number) => ["diagnostics", "event", id] as const,
|
||||
/** Prefix of every diagnostics entry, page and detail alike; the purge target. */
|
||||
diagnosticsAll: ["diagnostics"] as const,
|
||||
upstreamHealth: (period: Period) => ["upstream-health", period] as const,
|
||||
lookup: (domain: string, groupId?: number) => ["lookup", domain, groupId ?? null] as const,
|
||||
/** Prefix of every `lookup` entry; the invalidation target after any verdict input changes. */
|
||||
lookupAll: ["lookup"] as const,
|
||||
@@ -43,7 +45,6 @@ export const queryKeys = {
|
||||
clients: ["clients"] as const,
|
||||
clientPrefixes: ["client-prefixes"] as const,
|
||||
upstreams: ["upstreams"] as const,
|
||||
pause: ["pause"] as const,
|
||||
settings: ["settings"] as const,
|
||||
};
|
||||
|
||||
@@ -63,6 +64,27 @@ export const timeseriesQuery = (period: Period = "24h") =>
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const statsTypesQuery = (period: Period = "24h") =>
|
||||
queryOptions({
|
||||
queryKey: queryKeys.statsTypes(period),
|
||||
queryFn: () => api.getStatsTypes(period),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const statsRoutesQuery = (period: Period = "24h") =>
|
||||
queryOptions({
|
||||
queryKey: queryKeys.statsRoutes(period),
|
||||
queryFn: () => api.getStatsRoutes(period),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const statsClientsQuery = (period: Period = "24h") =>
|
||||
queryOptions({
|
||||
queryKey: queryKeys.statsClients(period),
|
||||
queryFn: () => api.getStatsClients(period),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
// Keyset pagination on `next_before` (handlers/queries.zig). A background
|
||||
// refetch replays every page in cursor order, so newly logged rows shift the
|
||||
// whole window instead of opening a gap between page 1 and page 2.
|
||||
@@ -101,16 +123,6 @@ export const diagnosticsInfiniteQuery = (filter: DiagnosticsFilter = {}, enabled
|
||||
export const diagnosticQuery = (id: number) =>
|
||||
queryOptions({ queryKey: queryKeys.diagnostic(id), queryFn: () => api.getDiagnostic(id) });
|
||||
|
||||
// The period is part of the key: the upstream aggregates are ranged like the
|
||||
// stats ones, so the picker has to refetch them rather than reuse a cached
|
||||
// window under a new label.
|
||||
export const upstreamHealthQuery = (period: Period = "24h") =>
|
||||
queryOptions({
|
||||
queryKey: queryKeys.upstreamHealth(period),
|
||||
queryFn: () => api.getUpstreamHealth(period),
|
||||
refetchInterval: 30_000,
|
||||
});
|
||||
|
||||
export const lookupQuery = (domain: string, groupId?: number) =>
|
||||
queryOptions({ queryKey: queryKeys.lookup(domain, groupId), queryFn: () => api.getLookup(domain, groupId) });
|
||||
|
||||
@@ -136,8 +148,6 @@ export const clientPrefixesQuery = () =>
|
||||
|
||||
export const upstreamsQuery = () => queryOptions({ queryKey: queryKeys.upstreams, queryFn: api.listUpstreams });
|
||||
|
||||
export const pauseQuery = () => queryOptions({ queryKey: queryKeys.pause, queryFn: api.getPause });
|
||||
|
||||
export const settingsQuery = () => queryOptions({ queryKey: queryKeys.settings, queryFn: api.getSettings });
|
||||
|
||||
// Mutation option factories. Usage: useMutation(groupCreateMutation(useQueryClient())).
|
||||
@@ -322,11 +332,13 @@ export const upstreamDeleteMutation = (qc: QueryClient) => ({
|
||||
onSuccess: () => invalidateUpstreams(qc),
|
||||
});
|
||||
|
||||
// Protection is a health condition, and health is the only thing that reads it:
|
||||
// the sidebar control, the Diagnostics health strip and the related action on a
|
||||
// blocked query all render `Health.protection`. Without this invalidation they
|
||||
// would contradict a successful mutation until the next ten-second poll.
|
||||
export const pauseMutation = (qc: QueryClient) => ({
|
||||
mutationFn: (body: PausePost) => api.postPause(body),
|
||||
onSuccess: (state: Awaited<ReturnType<typeof api.postPause>>) => {
|
||||
qc.setQueryData(queryKeys.pause, state);
|
||||
},
|
||||
onSuccess: () => qc.invalidateQueries({ queryKey: queryKeys.health }),
|
||||
});
|
||||
|
||||
export const settingsPutMutation = (qc: QueryClient) => ({
|
||||
|
||||
Reference in New Issue
Block a user