@@ -16,11 +16,7 @@ import {
1616 ChartConfigWithDateRange ,
1717 ChartConfigWithOptDateRange ,
1818} from '@hyperdx/common-utils/dist/types' ;
19- import {
20- experimental_streamedQuery as streamedQuery ,
21- useQuery ,
22- UseQueryOptions ,
23- } from '@tanstack/react-query' ;
19+ import { useQuery , UseQueryOptions } from '@tanstack/react-query' ;
2420
2521import {
2622 convertDateRangeToGranularityString ,
@@ -52,6 +48,11 @@ type TQueryFnData = Pick<ResponseJSON<any>, 'data' | 'meta' | 'rows'> & {
5248 isComplete : boolean ;
5349} ;
5450
51+ type TChunk = {
52+ chunk : ResponseJSON < Record < string , string | number > > ;
53+ isComplete : boolean ;
54+ } ;
55+
5556const shouldUseChunking = (
5657 config : ChartConfigWithOptDateRange ,
5758) : config is ChartConfigWithDateRange & {
@@ -158,6 +159,19 @@ async function* fetchDataInChunks(
158159 }
159160}
160161
162+ /** Append the given chunk to the given accumulated result */
163+ function appendChunk (
164+ accumulated : TQueryFnData ,
165+ { chunk, isComplete } : TChunk ,
166+ ) : TQueryFnData {
167+ return {
168+ data : [ ...( chunk . data || [ ] ) , ...( accumulated ?. data || [ ] ) ] ,
169+ meta : chunk . meta ,
170+ rows : ( accumulated ?. rows || 0 ) + ( chunk . rows || 0 ) ,
171+ isComplete,
172+ } ;
173+ }
174+
161175/**
162176 * A hook providing data queried based on the provided chart config.
163177 *
@@ -186,36 +200,54 @@ export function useQueriedChartConfig(
186200 // Include disableQueryChunking in the query key to ensure that queries with the
187201 // same config but different disableQueryChunking values do not share a query
188202 queryKey : [ config , options ?. disableQueryChunking ?? false ] ,
189- queryFn : streamedQuery ( {
190- streamFn : context =>
191- fetchDataInChunks (
192- config ,
193- clickhouseClient ,
194- context . signal ,
195- options ?. disableQueryChunking ,
196- ) ,
197- /**
198- * This mode ensures that data remains in the cache until the next full streamed result is available.
199- * By default, the cache would be cleared before new data starts arriving, which results in the query briefly
200- * going back into the loading/pending state when multiple observers are sharing the query result resulting
201- * in flickering or render loops.
202- */
203- refetchMode : 'replace' ,
204- initialValue : {
203+ // TODO: Replace this with `streamedQuery` when it is no longer experimental. Use 'replace' refetch mode.
204+ // https://tanstack.com/query/latest/docs/reference/streamedQuery
205+ queryFn : async context => {
206+ const query = context . client
207+ . getQueryCache ( )
208+ . find ( { queryKey : context . queryKey , exact : true } ) ;
209+ const isRefetch = ! ! query && query . state . data !== undefined ;
210+
211+ const emptyValue : TQueryFnData = {
205212 data : [ ] ,
206213 meta : [ ] ,
207214 rows : 0 ,
208215 isComplete : false ,
209- } as TQueryFnData ,
210- reducer : ( acc , { chunk, isComplete } ) => {
211- return {
212- data : [ ...( chunk . data || [ ] ) , ...( acc ?. data || [ ] ) ] ,
213- meta : chunk . meta ,
214- rows : ( acc ?. rows || 0 ) + ( chunk . rows || 0 ) ,
215- isComplete,
216- } ;
217- } ,
218- } ) ,
216+ } ;
217+
218+ const chunks = fetchDataInChunks (
219+ config ,
220+ clickhouseClient ,
221+ context . signal ,
222+ options ?. disableQueryChunking ,
223+ ) ;
224+
225+ let accumulatedChunks : TQueryFnData = emptyValue ;
226+ for await ( const chunk of chunks ) {
227+ if ( context . signal . aborted ) {
228+ break ;
229+ }
230+
231+ accumulatedChunks = appendChunk ( accumulatedChunks , chunk ) ;
232+
233+ // When refetching, the cache is not updated until all chunks are fetched.
234+ if ( ! isRefetch ) {
235+ context . client . setQueryData < TQueryFnData > (
236+ context . queryKey ,
237+ accumulatedChunks ,
238+ ) ;
239+ }
240+ }
241+
242+ if ( isRefetch && ! context . signal . aborted ) {
243+ context . client . setQueryData < TQueryFnData > (
244+ context . queryKey ,
245+ accumulatedChunks ,
246+ ) ;
247+ }
248+
249+ return context . client . getQueryData ( context . queryKey ) ! ;
250+ } ,
219251 retry : 1 ,
220252 refetchOnWindowFocus : false ,
221253 ...options ,
0 commit comments