Skip to content

Commit 3a2c33d

Browse files
authored
feat: debounce highlighted attribute validation query (#1626)
Follow up to #1576 after feedback from @MikeShi42. With these changes, validation queries run either when the "Validate expression" button is clicked, or 1 second after the input value was changed for either the expression or the alias. https://github.com/user-attachments/assets/8a42e3cd-e9da-40a3-95c2-8b037ab766e4
1 parent cf71a1c commit 3a2c33d

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

.changeset/mighty-crabs-tan.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hyperdx/app": patch
3+
---
4+
5+
feat: debounce highlighted attribute validation query

packages/app/src/components/Sources/SourceForm.tsx

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
Tooltip,
4242
} from '@mantine/core';
4343
import { DateInput } from '@mantine/dates';
44+
import { useDebouncedCallback, useDidUpdate } from '@mantine/hooks';
4445
import { notifications } from '@mantine/notifications';
4546
import {
4647
IconCheck,
@@ -201,41 +202,72 @@ function HighlightedAttributeRow({
201202
connectionId,
202203
removeHighlightedAttribute,
203204
}: HighlightedAttributeRowProps) {
204-
const expression = useWatch({
205+
const expressionInput = useWatch({
205206
control,
206207
name: `${name}.${index}.sqlExpression`,
207208
});
208209

209-
const alias = useWatch({
210+
const aliasInput = useWatch({
210211
control,
211212
name: `${name}.${index}.alias`,
212213
});
213214

215+
const [explainParams, setExplainParams] = useState<{
216+
expression: typeof expressionInput;
217+
alias: typeof aliasInput;
218+
}>();
219+
220+
const setExplainParamsDebounced = useDebouncedCallback(
221+
(params: typeof explainParams) => {
222+
setExplainParams(params);
223+
},
224+
1_000,
225+
);
226+
227+
useDidUpdate(() => {
228+
setExplainParamsDebounced({
229+
expression: expressionInput,
230+
alias: aliasInput,
231+
});
232+
}, [expressionInput, aliasInput]);
233+
214234
const {
215235
data: explainData,
216236
error: explainError,
217237
isLoading: explainLoading,
218-
refetch: explainExpression,
219238
} = useExplainQuery(
220239
{
221240
from: { databaseName, tableName },
222241
connection: connectionId,
223-
select: [{ alias, valueExpression: expression }],
242+
select: [
243+
{
244+
alias: explainParams?.alias,
245+
valueExpression: explainParams?.expression ?? '',
246+
},
247+
],
224248
where: '',
225249
},
226250

227-
{ enabled: false },
251+
{
252+
enabled: !!explainParams?.expression,
253+
},
228254
);
229255

230256
const runExpression = () => {
231-
if (expression) {
232-
explainExpression();
233-
}
257+
setExplainParams({
258+
expression: expressionInput,
259+
alias: aliasInput,
260+
});
234261
};
235262

236263
const isExpressionValid = !!explainData?.length;
237264
const isExpressionInvalid = explainError instanceof ClickHouseQueryError;
238265

266+
const shouldShowResult =
267+
explainParams?.expression === expressionInput &&
268+
explainParams?.alias === aliasInput &&
269+
(isExpressionValid || isExpressionInvalid);
270+
239271
return (
240272
<React.Fragment key={id}>
241273
<Grid.Col span={3} pe={0}>
@@ -271,7 +303,7 @@ function HighlightedAttributeRow({
271303
variant="subtle"
272304
color="gray"
273305
loading={explainLoading}
274-
disabled={!expression || explainLoading}
306+
disabled={!expressionInput || explainLoading}
275307
onClick={runExpression}
276308
>
277309
<IconCheck size={16} />
@@ -288,7 +320,7 @@ function HighlightedAttributeRow({
288320
</Flex>
289321
</Grid.Col>
290322

291-
{(isExpressionValid || isExpressionInvalid) && (
323+
{shouldShowResult && (
292324
<Grid.Col span={5} pe={0} pt={0}>
293325
{isExpressionValid && (
294326
<Text c="green" size="xs">

0 commit comments

Comments
 (0)