From a4ef5cdf615fdef1350929b701b7e3436bd24de1 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Fri, 28 Mar 2025 17:30:02 -0600 Subject: [PATCH] update query keys --- web/src/api/query_keys/chat.ts | 4 +- web/src/api/query_keys/dashboard.ts | 4 +- web/src/api/query_keys/metric.ts | 4 +- .../BusterReactQuery/createPersister.ts | 47 ++++++++++++++----- .../BusterReactQuery/getQueryClient.ts | 30 ++++-------- 5 files changed, 50 insertions(+), 39 deletions(-) diff --git a/web/src/api/query_keys/chat.ts b/web/src/api/query_keys/chat.ts index e1e4dd370..8db3cf1aa 100644 --- a/web/src/api/query_keys/chat.ts +++ b/web/src/api/query_keys/chat.ts @@ -28,7 +28,7 @@ const chatsGetList = ( filters?: Omit[0], 'page_token' | 'page_size'> ) => queryOptions({ - queryKey: ['chats', 'list', filters] as const, + queryKey: ['chats', 'list', filters || {}] as const, staleTime: 60 * 1000, // 1 minute initialData: [], initialDataUpdatedAt: 0 @@ -46,7 +46,7 @@ const logsGetList = ( filters?: Omit[0], 'page_token' | 'page_size'> ) => queryOptions({ - queryKey: ['logs', 'list', filters] as const, + queryKey: ['logs', 'list', filters || {}] as const, staleTime: 60 * 1000, // 1 minute initialData: [], initialDataUpdatedAt: 0 diff --git a/web/src/api/query_keys/dashboard.ts b/web/src/api/query_keys/dashboard.ts index fad3fb342..77db00462 100644 --- a/web/src/api/query_keys/dashboard.ts +++ b/web/src/api/query_keys/dashboard.ts @@ -6,10 +6,10 @@ import type { import { dashboardsGetList } from '../buster_rest/dashboards'; const dashboardGetList = ( - filters: Omit[0], 'page_token' | 'page_size'> + filters?: Omit[0], 'page_token' | 'page_size'> ) => queryOptions({ - queryKey: ['dashboard', 'list', filters] as const, + queryKey: ['dashboard', 'list', filters || {}] as const, initialData: [], staleTime: 60 * 1000, initialDataUpdatedAt: 0 diff --git a/web/src/api/query_keys/metric.ts b/web/src/api/query_keys/metric.ts index 069b3e832..474c57c80 100644 --- a/web/src/api/query_keys/metric.ts +++ b/web/src/api/query_keys/metric.ts @@ -14,10 +14,10 @@ export const metricsGetMetric = (metricId: string, version_number?: number) => { }; export const metricsGetList = ( - filters: Omit[0], 'page_token' | 'page_size'> + filters?: Omit[0], 'page_token' | 'page_size'> ) => queryOptions({ - queryKey: ['metrics', 'list', filters] as const, + queryKey: ['metrics', 'list', filters || {}] as const, initialData: [], initialDataUpdatedAt: 0 }); diff --git a/web/src/context/BusterReactQuery/createPersister.ts b/web/src/context/BusterReactQuery/createPersister.ts index 1c5f1306a..d3e3b3815 100644 --- a/web/src/context/BusterReactQuery/createPersister.ts +++ b/web/src/context/BusterReactQuery/createPersister.ts @@ -7,25 +7,43 @@ import packageJson from '../../../package.json'; const buster = packageJson.version; -export const PERSIST_TIME = 1000 * 60 * 60 * 24 * 3; // 3 days - -const persister = createSyncStoragePersister({ - storage: isServer ? undefined : window.localStorage, - throttleTime: 1500 // 1.5 seconds -}); +export const PERSIST_TIME = 1000 * 60 * 60 * 24 * 7; // 7 days export const PERSISTED_QUERIES = [ queryKeys.favoritesGetList.queryKey, - queryKeys.logsGetList({}).queryKey, - queryKeys.chatsGetList({}).queryKey, - queryKeys.dashboardGetList({}).queryKey, - queryKeys.metricsGetList({}).queryKey, - queryKeys.collectionsGetList({}).queryKey + queryKeys.logsGetList().queryKey, + queryKeys.chatsGetList().queryKey, + queryKeys.dashboardGetList().queryKey, + queryKeys.metricsGetList().queryKey, + queryKeys.collectionsGetList().queryKey, + queryKeys.termsGetList.queryKey, + queryKeys.datasetsListQueryOptions().queryKey ].map(hashKey); export const PERMANENT_QUERIES = [queryKeys.getCurrencies.queryKey].map(hashKey); const ALL_PERSISTED_QUERIES = [...PERSISTED_QUERIES, ...PERMANENT_QUERIES]; + +const persister = createSyncStoragePersister({ + key: 'buster-query-cache', + storage: isServer ? undefined : window.localStorage, + throttleTime: 1500, // 1.5 seconds, + serialize: (client) => { + /* + * Make persisted queries appear stale on first load by setting the dataUpdatedAt to 1 (NOT 0) + * This way the query will be refetched from the server when it is first mounted AND we + * don't have to deal with the flash of stale data that would otherwise happen. + */ + client.clientState.queries.forEach((query) => { + const isPermanentQuery = PERMANENT_QUERIES.includes(query.queryHash); + if (!isPermanentQuery) { + query.state.dataUpdatedAt = 1; + } + }); + return JSON.stringify(client); + } +}); + export const persistOptions: PersistQueryClientProviderProps['persistOptions'] = { persister: persister, maxAge: PERSIST_TIME, @@ -34,5 +52,12 @@ export const persistOptions: PersistQueryClientProviderProps['persistOptions'] = return ALL_PERSISTED_QUERIES.includes(query.queryHash); } }, + hydrateOptions: { + defaultOptions: { + queries: { + initialDataUpdatedAt: 0 + } + } + }, buster: buster }; diff --git a/web/src/context/BusterReactQuery/getQueryClient.ts b/web/src/context/BusterReactQuery/getQueryClient.ts index a7cbee8e0..7153b6e9c 100644 --- a/web/src/context/BusterReactQuery/getQueryClient.ts +++ b/web/src/context/BusterReactQuery/getQueryClient.ts @@ -1,7 +1,7 @@ -import { QueryClient, defaultShouldDehydrateQuery, isServer } from '@tanstack/react-query'; +import { QueryClient, defaultShouldDehydrateQuery, isServer, Query } from '@tanstack/react-query'; import { useBusterNotifications } from '../BusterNotifications'; import { openErrorNotification as openErrorNotificationMethod } from '../BusterNotifications'; -import { PERMANENT_QUERIES } from './createPersister'; +import { PERMANENT_QUERIES, PERSISTED_QUERIES } from './createPersister'; type OpenErrorNotification = ReturnType['openErrorNotification']; @@ -9,8 +9,8 @@ const PREFETCH_STALE_TIME = 1000 * 10; // 10 seconds const ERROR_RETRY_DELAY = 1 * 1000; // 1 second delay after error const GC_TIME = 1000 * 60 * 60 * 24 * 3; // 24 hours - matches persistence duration -// Track queries that have already mounted -const mountedQueries = new Set(); +// Track which queries have been initialized +const initializedQueries = new Set(); function makeQueryClient(params?: { openErrorNotification?: OpenErrorNotification; @@ -24,7 +24,9 @@ function makeQueryClient(params?: { refetchOnWindowFocus: false, staleTime: PREFETCH_STALE_TIME, gcTime: GC_TIME, - enabled: (params?.enabled ?? true) && baseEnabled, + enabled: () => { + return (params?.enabled ?? true) && baseEnabled; + }, queryFn: () => Promise.resolve(), retry: (failureCount, error) => { if (params?.openErrorNotification) { @@ -32,23 +34,7 @@ function makeQueryClient(params?: { } return false; }, - retryDelay: ERROR_RETRY_DELAY, - refetchOnMount: (query) => { - console.log(query.queryHash, query.state.dataUpdatedAt); - if (!query.state.dataUpdatedAt) { - // No data has been fetched yet - return true; - } - - if (!mountedQueries.has(query.queryHash) && query.isActive()) { - // First time mounting this query - mountedQueries.add(query.queryHash); - return 'always'; - } - - // Query has mounted before, use default stale time behavior - return query.state.dataUpdatedAt < Date.now() - PREFETCH_STALE_TIME; - } + retryDelay: ERROR_RETRY_DELAY }, mutations: { retry: (failureCount, error) => {