fix: optimize query key for aliasMap to prevent jitter (#1351)

Fixes: HDX-2787

During live tail, the date range changes every few seconds (e.g., from 9:00-9:15 to 9:02-9:17, etc...). The original aliasMap query key included the entire config object, which contains the dateRange property. Every date range change triggered a refetch of the alias map, even though aliases are derived from the SELECT statement and not from the date range.

While refetching, react-query sets aliasMap to undefined. This caused column IDs to change.  React-table uses column IDs as keys to track resize state, so when the ID changes, it loses the stored width and resets to the default size, causing the visible jitter.

Now we have a consistent aliasMap with the added benefit of less network requests.
This commit is contained in:
Tom Alexander 2025-11-12 13:24:44 -05:00 committed by GitHub
parent 64b5673089
commit 63fcf145cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 6 deletions

View file

@ -0,0 +1,5 @@
---
"@hyperdx/app": patch
---
fix: optimize query key for aliasMap to prevent jitter

View file

@ -57,7 +57,7 @@ import {
useDocumentVisibility,
} from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { keepPreviousData, useIsFetching } from '@tanstack/react-query';
import { useIsFetching } from '@tanstack/react-query';
import { SortingState } from '@tanstack/react-table';
import CodeMirror from '@uiw/react-codemirror';
@ -1147,10 +1147,7 @@ function DBSearchPage() {
}
}, [isReady, queryReady, isChartConfigLoading, onSearch]);
const { data: aliasMap } = useAliasMapFromChartConfig(dbSqlRowTableConfig, {
placeholderData: keepPreviousData,
queryKey: ['aliasMap', dbSqlRowTableConfig, 'withPlaceholder'],
});
const { data: aliasMap } = useAliasMapFromChartConfig(dbSqlRowTableConfig);
const aliasWith = useMemo(
() =>

View file

@ -286,8 +286,30 @@ export function useAliasMapFromChartConfig(
config: ChartConfigWithOptDateRange | undefined,
options?: UseQueryOptions<Record<string, string>>,
) {
// For granularity: 'auto', the bucket size depends on dateRange duration (not absolute times).
// Include duration in key to detect when bucket size changes, but omit absolute times
// to prevent refetches when the time window just slides forward (e.g., live tail).
const dateRangeDuration =
config?.dateRange && isUsingGranularity(config)
? config.dateRange[1].getTime() - config.dateRange[0].getTime()
: undefined;
return useQuery<Record<string, string>>({
queryKey: ['aliasMap', config],
// Only include config properties that affect SELECT structure and aliases.
// When adding new ChartConfig fields, check renderChartConfig.ts to see if they
// affect the SELECT clause. If yes, add them here to avoid stale alias maps.
queryKey: [
'aliasMap',
config?.select,
config?.from,
config?.connection,
config?.with,
config?.groupBy,
config?.selectGroupBy,
config?.granularity,
config?.seriesReturnType,
dateRangeDuration,
],
queryFn: async () => {
if (config == null) {
return {};