Skip to content

Commit 9d90dff

Browse files
authored
feat: cancel queries in query builder when toggling between values (#4466)
1 parent 05f7bd0 commit 9d90dff

File tree

3 files changed

+89
-30
lines changed

3 files changed

+89
-30
lines changed

src/flows/pipes/QueryBuilder/CardList.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ const Card: FC<Props> = ({idx}) => {
5959
cards,
6060
selectMeasurement,
6161
add,
62+
cancelKey,
63+
cancelValue,
6264
update,
6365
remove,
6466
loadKeys,
@@ -131,8 +133,7 @@ const Card: FC<Props> = ({idx}) => {
131133
card.values.selected.length <= 1
132134

133135
const valueSelect = val => {
134-
const _vals = [...card.values.selected]
135-
const index = _vals.indexOf(val)
136+
const index = card.values.selected.indexOf(val)
136137

137138
if (isCompliant) {
138139
if (index === -1) {
@@ -148,20 +149,19 @@ const Card: FC<Props> = ({idx}) => {
148149

149150
if (index === -1) {
150151
event('Query Builder Value Selected')
151-
_vals.push(val)
152+
card.values.selected.push(val)
152153
} else {
153154
event('Query Builder Value Unselected')
154-
_vals.splice(index, 1)
155+
card.values.selected.splice(index, 1)
155156
}
156157

157-
update(idx, {
158-
values: {
159-
...card.values,
160-
selected: _vals,
161-
},
162-
})
158+
update(idx, card)
163159

164-
if (index === -1 && _vals.length === 1 && idx === cards.length - 1) {
160+
if (
161+
index === -1 &&
162+
card.values.selected.length === 1 &&
163+
idx === cards.length - 1
164+
) {
165165
add()
166166
} else {
167167
for (let ni = idx + 1; ni < cards.length; ni++) {
@@ -171,17 +171,38 @@ const Card: FC<Props> = ({idx}) => {
171171
}
172172

173173
useEffect(() => {
174+
let promise
174175
if (data.buckets[0] && card.keys.loading === RemoteDataState.NotStarted) {
175-
loadKeys(idx)
176+
promise = loadKeys(idx)
177+
if (promise instanceof Promise) {
178+
promise.finally(() => {
179+
promise = null
180+
})
181+
}
182+
}
183+
184+
return () => {
185+
cancelKey(idx)
176186
}
177187
}, [data.buckets, card.keys.loading])
178188

179189
useEffect(() => {
190+
let promise
180191
if (
181192
card.keys.loading === RemoteDataState.Done &&
182193
card.values.loading !== RemoteDataState.Done
183194
) {
184-
loadValues(idx)
195+
promise = loadValues(idx)
196+
197+
if (promise instanceof Promise) {
198+
promise.finally(() => {
199+
promise = null
200+
})
201+
}
202+
}
203+
204+
return () => {
205+
cancelValue(idx)
185206
}
186207
}, [card.keys.loading, card.values.loading])
187208

src/flows/pipes/QueryBuilder/context.tsx

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Libraries
2-
import React, {FC, createContext, useContext, useState, useMemo} from 'react'
2+
import React, {FC, createContext, useContext, useState} from 'react'
33

44
// Contexts
55
import {PipeContext} from 'src/flows/context/pipe'
@@ -63,10 +63,12 @@ interface QueryBuilderContextType {
6363
selectMeasurement: (measurement?: string) => void
6464

6565
add: () => void
66+
cancelKey: (idx: number) => void
67+
cancelValue: (idx: number) => void
6668
remove: (idx: number) => void
6769
update: (idx: number, card: Partial<QueryBuilderCard>) => void
68-
loadKeys: (idx: number, search?: string) => void
69-
loadValues: (idx: number, search?: string) => void
70+
loadKeys: (idx: number, search?: string) => void | Promise<any>
71+
loadValues: (idx: number, search?: string) => void | Promise<any>
7072
}
7173

7274
export const DEFAULT_CONTEXT: QueryBuilderContextType = {
@@ -76,6 +78,8 @@ export const DEFAULT_CONTEXT: QueryBuilderContextType = {
7678
selectMeasurement: _ => {},
7779

7880
add: () => {},
81+
cancelKey: (_idx: number) => {},
82+
cancelValue: (_idx: number) => {},
7983
remove: (_idx: number) => {},
8084
update: (_idx: number, _card: QueryBuilderCard) => {},
8185
loadKeys: (_idx: number, _search?: string) => {},
@@ -113,6 +117,8 @@ export const QueryBuilderProvider: FC = ({children}) => {
113117
const {id, data, range, update} = useContext(PipeContext)
114118
const {query, getPanelQueries} = useContext(FlowQueryContext)
115119
const {buckets} = useContext(BucketContext)
120+
const [cancelKey, setCancelKey] = useState({})
121+
const [cancelValue, setCancelValue] = useState({})
116122

117123
const [cardMeta, setCardMeta] = useState<QueryBuilderMeta[]>(
118124
Array(data.tags.length).fill({
@@ -181,9 +187,8 @@ export const QueryBuilderProvider: FC = ({children}) => {
181187
}
182188
}
183189

184-
const cards = useMemo(
185-
() => data.tags.map((tag, idx) => fromBuilderConfig(tag, cardMeta[idx])),
186-
[data.tags, cardMeta]
190+
const cards = data.tags.map((tag, idx) =>
191+
fromBuilderConfig(tag, cardMeta[idx])
187192
)
188193

189194
const add = () => {
@@ -294,23 +299,31 @@ export const QueryBuilderProvider: FC = ({children}) => {
294299
|> limit(n: ${limit})`
295300
}
296301

297-
query(queryText, scope)
302+
const result = query(queryText, scope)
303+
304+
setCancelKey(prev => ({
305+
...prev,
306+
[idx]: (result as any).cancel,
307+
}))
308+
309+
return result
298310
.then(resp => {
299311
return (Object.values(resp.parsed.table.columns).filter(
300312
c => c.name === '_value' && c.type === 'string'
301313
)[0]?.data ?? []) as string[]
302314
})
303315
.then(keys => {
304-
if (!cards[idx].keys.selected[0]) {
316+
const currentCards = data.tags.map(fromBuilderConfig)
317+
if (!currentCards[idx].keys.selected[0]) {
305318
if (idx === 0 && keys.includes('_measurement')) {
306-
cards[idx].keys.selected = ['_measurement']
319+
currentCards[idx].keys.selected = ['_measurement']
307320
} else {
308-
cards[idx].keys.selected = [keys[0]]
321+
currentCards[idx].keys.selected = [keys[0]]
309322
}
310323

311-
update({tags: cards.map(toBuilderConfig)})
312-
} else if (!keys.includes(cards[idx].keys.selected[0])) {
313-
keys.unshift(cards[idx].keys.selected[0])
324+
update({tags: currentCards.map(toBuilderConfig)})
325+
} else if (!keys.includes(currentCards[idx].keys.selected[0])) {
326+
keys.unshift(currentCards[idx].keys.selected[0])
314327
}
315328

316329
cardMeta.splice(idx, 1, {
@@ -326,6 +339,18 @@ export const QueryBuilderProvider: FC = ({children}) => {
326339
})
327340
}
328341

342+
const handleCancelKey = idx => {
343+
if (idx in cancelKey) {
344+
cancelKey[idx]()
345+
}
346+
}
347+
348+
const handleCancelValue = idx => {
349+
if (idx in cancelValue) {
350+
cancelValue[idx]()
351+
}
352+
}
353+
329354
const loadValues = (idx, search) => {
330355
if (
331356
cardMeta[idx].loadingValues === RemoteDataState.Loading ||
@@ -402,7 +427,14 @@ export const QueryBuilderProvider: FC = ({children}) => {
402427
|> sort()`
403428
}
404429

405-
query(queryText, scope)
430+
const result = query(queryText, scope)
431+
432+
setCancelValue(prev => ({
433+
...prev,
434+
[idx]: (result as any).cancel,
435+
}))
436+
437+
return result
406438
.then(resp => {
407439
return (Object.values(resp.parsed.table.columns).filter(
408440
c => c.name === '_value' && c.type === 'string'
@@ -480,7 +512,9 @@ export const QueryBuilderProvider: FC = ({children}) => {
480512
..._card,
481513
}
482514

483-
update({tags: cards.map(toBuilderConfig)})
515+
data.tags = cards.map(toBuilderConfig)
516+
517+
update({tags: data.tags})
484518
}
485519

486520
return (
@@ -490,7 +524,8 @@ export const QueryBuilderProvider: FC = ({children}) => {
490524

491525
selectBucket,
492526
selectMeasurement,
493-
527+
cancelKey: handleCancelKey,
528+
cancelValue: handleCancelValue,
494529
add,
495530
remove,
496531
update: updater,

src/shared/contexts/query.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ export const QueryProvider: FC = ({children}) => {
564564
const query = (text: string, override?: QueryScope): Promise<FluxResult> => {
565565
const result = basic(text, override)
566566

567-
return result.promise
567+
const promise: any = result.promise
568568
.then(raw => {
569569
if (raw.type !== 'SUCCESS') {
570570
throw new Error(raw.message)
@@ -586,6 +586,9 @@ export const QueryProvider: FC = ({children}) => {
586586
error: null,
587587
} as FluxResult)
588588
)
589+
590+
promise.cancel = result.cancel
591+
return promise
589592
}
590593

591594
if (bucketsLoadingState !== RemoteDataState.Done) {

0 commit comments

Comments
 (0)