Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.

Commit 7ce20c0

Browse files
authored
fix: upgrade to useQuery in explore page (#360)
1 parent 30b8d61 commit 7ce20c0

File tree

4 files changed

+133
-126
lines changed

4 files changed

+133
-126
lines changed

package.json

Lines changed: 85 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,87 @@
11
{
2-
"name": "parseable-console",
3-
"version": "0.1.0",
4-
"private": true,
5-
"type": "module",
6-
"scripts": {
7-
"dev": "vite --host --port 3001",
8-
"build": "tsc && vite build",
9-
"build:test": "tsc && vite build --mode test",
10-
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
11-
"start": "vite preview --host --port 3002",
12-
"tsCheck": "tsc --noEmit",
13-
"pq": "pretty-quick"
14-
},
15-
"dependencies": {
16-
"@apache-arrow/ts": "^14.0.2",
17-
"@emotion/react": "^11.11.1",
18-
"@mantine/carousel": "^7.8.1",
19-
"@mantine/charts": "^7.8.1",
20-
"@mantine/code-highlight": "^7.8.1",
21-
"@mantine/core": "^7.8.1",
22-
"@mantine/dates": "^7.8.1",
23-
"@mantine/form": "^7.8.1",
24-
"@mantine/hooks": "^7.8.1",
25-
"@mantine/notifications": "^7.8.1",
26-
"@monaco-editor/react": "^4.5.1",
27-
"@tabler/icons-react": "^3.3.0",
28-
"@types/js-cookie": "^3.0.3",
29-
"axios": "^1.4.0",
30-
"dayjs": "^1.11.10",
31-
"embla-carousel-react": "7.1.0",
32-
"html2canvas": "^1.4.1",
33-
"http-status-codes": "^2.2.0",
34-
"immer": "^10.0.2",
35-
"jq-web": "^0.5.1",
36-
"js-cookie": "^3.0.5",
37-
"just-compare": "^2.3.0",
38-
"lodash": "^4.17.21",
39-
"long": "^5.2.3",
40-
"mantine-react-table": "2.0.0-beta.6",
41-
"moment-timezone": "^0.5.45",
42-
"ms": "^2.1.3",
43-
"nice-grpc-common": "^2.0.2",
44-
"nice-grpc-web": "^3.3.2",
45-
"protobufjs": "^7.2.5",
46-
"react": "^18.2.0",
47-
"react-beautiful-dnd": "^13.1.1",
48-
"react-dom": "^18.2.0",
49-
"react-error-boundary": "^4.0.10",
50-
"react-grid-layout": "^1.4.4",
51-
"react-query": "^3.39.3",
52-
"react-querybuilder": "^6.5.5",
53-
"react-resizable": "^3.0.5",
54-
"react-resizable-panels": "^0.0.53",
55-
"react-router-dom": "^6.14.0",
56-
"react-window": "^1.8.9"
57-
},
58-
"devDependencies": {
59-
"@playwright/test": "^1.48.2",
60-
"@types/lodash": "^4.17.0",
61-
"@types/ms": "^0.7.31",
62-
"@types/node": "^20.3.2",
63-
"@types/react": "^18.2.14",
64-
"@types/react-beautiful-dnd": "^13.1.4",
65-
"@types/react-dom": "^18.2.6",
66-
"@types/react-grid-layout": "^1.3.5",
67-
"@types/react-resizable": "^3.0.8",
68-
"@types/react-window": "^1.8.5",
69-
"@typescript-eslint/eslint-plugin": "^5.60.1",
70-
"@typescript-eslint/parser": "^5.60.1",
71-
"@vitejs/plugin-react-swc": "^3.3.2",
72-
"eslint": "^8.43.0",
73-
"eslint-config-prettier": "^8.8.0",
74-
"eslint-plugin-import": "^2.27.5",
75-
"eslint-plugin-prettier": "^4.2.1",
76-
"eslint-plugin-react": "^7.32.2",
77-
"eslint-plugin-react-hooks": "^4.6.0",
78-
"eslint-plugin-react-refresh": "^0.4.1",
79-
"postcss": "^8.4.33",
80-
"postcss-preset-mantine": "^1.13.0",
81-
"postcss-simple-vars": "^7.0.1",
82-
"prettier": "^2.8.8",
83-
"pretty-quick": "^3.1.3",
84-
"typescript": "^5.1.6",
85-
"vite": "^4.3.9"
86-
}
2+
"name": "parseable-console",
3+
"version": "0.1.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"dev": "vite --host --port 3001",
8+
"build": "tsc && vite build",
9+
"build:test": "tsc && vite build --mode test",
10+
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
11+
"start": "vite preview --host --port 3002",
12+
"tsCheck": "tsc --noEmit",
13+
"pq": "pretty-quick"
14+
},
15+
"dependencies": {
16+
"@apache-arrow/ts": "^14.0.2",
17+
"@emotion/react": "^11.11.1",
18+
"@mantine/carousel": "^7.8.1",
19+
"@mantine/charts": "^7.8.1",
20+
"@mantine/code-highlight": "^7.8.1",
21+
"@mantine/core": "^7.8.1",
22+
"@mantine/dates": "^7.8.1",
23+
"@mantine/form": "^7.8.1",
24+
"@mantine/hooks": "^7.8.1",
25+
"@mantine/notifications": "^7.8.1",
26+
"@monaco-editor/react": "^4.5.1",
27+
"@tabler/icons-react": "^3.3.0",
28+
"@types/js-cookie": "^3.0.3",
29+
"axios": "^1.4.0",
30+
"dayjs": "^1.11.10",
31+
"embla-carousel-react": "7.1.0",
32+
"html2canvas": "^1.4.1",
33+
"http-status-codes": "^2.2.0",
34+
"immer": "^10.0.2",
35+
"jq-web": "^0.5.1",
36+
"js-cookie": "^3.0.5",
37+
"just-compare": "^2.3.0",
38+
"lodash": "^4.17.21",
39+
"long": "^5.2.3",
40+
"mantine-react-table": "2.0.0-beta.6",
41+
"moment-timezone": "^0.5.45",
42+
"ms": "^2.1.3",
43+
"nice-grpc-common": "^2.0.2",
44+
"nice-grpc-web": "^3.3.2",
45+
"protobufjs": "^7.2.5",
46+
"react": "^18.2.0",
47+
"react-beautiful-dnd": "^13.1.1",
48+
"react-dom": "^18.2.0",
49+
"react-error-boundary": "^4.0.10",
50+
"react-grid-layout": "^1.4.4",
51+
"react-query": "^3.39.3",
52+
"react-querybuilder": "^6.5.5",
53+
"react-resizable": "^3.0.5",
54+
"react-resizable-panels": "^0.0.53",
55+
"react-router-dom": "^6.14.0",
56+
"react-window": "^1.8.9"
57+
},
58+
"devDependencies": {
59+
"@playwright/test": "^1.48.2",
60+
"@types/lodash": "^4.17.0",
61+
"@types/ms": "^0.7.31",
62+
"@types/node": "^20.3.2",
63+
"@types/react": "^18.2.14",
64+
"@types/react-beautiful-dnd": "^13.1.4",
65+
"@types/react-dom": "^18.2.6",
66+
"@types/react-grid-layout": "^1.3.5",
67+
"@types/react-resizable": "^3.0.8",
68+
"@types/react-window": "^1.8.5",
69+
"@typescript-eslint/eslint-plugin": "^5.60.1",
70+
"@typescript-eslint/parser": "^5.60.1",
71+
"@vitejs/plugin-react-swc": "^3.3.2",
72+
"eslint": "^8.43.0",
73+
"eslint-config-prettier": "^8.8.0",
74+
"eslint-plugin-import": "^2.27.5",
75+
"eslint-plugin-prettier": "^4.2.1",
76+
"eslint-plugin-react": "^7.32.2",
77+
"eslint-plugin-react-hooks": "^4.6.0",
78+
"eslint-plugin-react-refresh": "^0.4.1",
79+
"postcss": "^8.4.33",
80+
"postcss-preset-mantine": "^1.13.0",
81+
"postcss-simple-vars": "^7.0.1",
82+
"prettier": "^2.8.8",
83+
"pretty-quick": "^3.1.3",
84+
"typescript": "^5.1.6",
85+
"vite": "^4.3.9"
86+
}
8787
}

src/hooks/useQueryLogs.ts

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { SortOrder, type Log, type LogsData, type LogsSearch } from '@/@types/pa
22
import { getQueryLogsWithHeaders, getQueryResultWithHeaders } from '@/api/query';
33
import { StatusCodes } from 'http-status-codes';
44
import useMountedState from './useMountedState';
5+
import { useQuery } from 'react-query';
56
import { useCallback, useRef } from 'react';
67
import { useLogsStore, logsStoreReducers, LOAD_LIMIT, isJqSearch } from '@/pages/Stream/providers/LogsProvider';
78
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
@@ -25,7 +26,6 @@ export const useQueryLogs = () => {
2526
// Only mutate it when data is fetched, otherwise read only
2627
const _dataRef = useRef<Log[] | null>(null);
2728
const [error, setError] = useMountedState<string | null>(null);
28-
const [loading, setLoading] = useMountedState<boolean>(false);
2929
const [pageLogData, setPageLogData] = useMountedState<LogsData | null>(null);
3030
const [querySearch, setQuerySearch] = useMountedState<LogsSearch>({
3131
search: '',
@@ -81,45 +81,50 @@ export const useQueryLogs = () => {
8181
pageOffset: currentOffset,
8282
timePartitionColumn,
8383
};
84-
const getQueryData = async () => {
85-
try {
86-
setLoading(true);
87-
setError(null);
88-
refetchSchema(); // fetch schema parallelly every time we fetch logs
89-
const logsQueryRes = await (async () => {
90-
if (isQuerySearchActive) {
91-
if (activeMode === 'filters') {
92-
const { parsedQuery } = parseQuery(queryEngine, appliedQuery, currentStream || '', {
93-
startTime: timeRange.startTime,
94-
endTime: timeRange.endTime,
95-
timePartitionColumn,
96-
});
97-
const queryStrWithOffset = appendOffsetToQuery(parsedQuery, defaultQueryOpts.pageOffset);
98-
return await getQueryResultWithHeaders({ ...defaultQueryOpts, access: [] }, queryStrWithOffset);
99-
} else {
100-
const queryStrWithOffset = appendOffsetToQuery(custSearchQuery, defaultQueryOpts.pageOffset);
101-
return await getQueryResultWithHeaders({ ...defaultQueryOpts, access: [] }, queryStrWithOffset);
102-
}
84+
85+
const {
86+
isLoading: logsLoading,
87+
isRefetching: logsRefetching,
88+
refetch: getQueryData,
89+
} = useQuery(
90+
['fetch-logs', defaultQueryOpts],
91+
() => {
92+
refetchSchema();
93+
if (isQuerySearchActive) {
94+
if (activeMode === 'filters') {
95+
const { parsedQuery } = parseQuery(queryEngine, appliedQuery, currentStream || '', {
96+
startTime: timeRange.startTime,
97+
endTime: timeRange.endTime,
98+
timePartitionColumn,
99+
});
100+
const queryStrWithOffset = appendOffsetToQuery(parsedQuery, defaultQueryOpts.pageOffset);
101+
return getQueryResultWithHeaders({ ...defaultQueryOpts, access: [] }, queryStrWithOffset);
103102
} else {
104-
return await getQueryLogsWithHeaders(defaultQueryOpts);
103+
const queryStrWithOffset = appendOffsetToQuery(custSearchQuery, defaultQueryOpts.pageOffset);
104+
return getQueryResultWithHeaders({ ...defaultQueryOpts, access: [] }, queryStrWithOffset);
105105
}
106-
})();
107-
const logs = logsQueryRes.data;
108-
const isInvalidResponse = _.isEmpty(logs) || _.isNil(logs) || logsQueryRes.status !== StatusCodes.OK;
109-
if (isInvalidResponse) return setError('Failed to query log');
106+
} else {
107+
return getQueryLogsWithHeaders(defaultQueryOpts);
108+
}
109+
},
110+
{
111+
enabled: false,
112+
refetchOnWindowFocus: false,
113+
onSuccess: async (data) => {
114+
const logs = data.data;
115+
const isInvalidResponse = _.isEmpty(logs) || _.isNil(logs) || data.status !== StatusCodes.OK;
116+
if (isInvalidResponse) return setError('Failed to query logs');
110117

111-
const { records, fields } = logs;
112-
const jqFilteredData = isJqSearch(instantSearchValue) ? await jqSearch(records, instantSearchValue) : [];
113-
return setLogsStore((store) => setLogData(store, records, fields, jqFilteredData));
114-
} catch (e) {
115-
const axiosError = e as AxiosError;
116-
const errorMessage = axiosError?.response?.data;
117-
setError(_.isString(errorMessage) && !_.isEmpty(errorMessage) ? errorMessage : 'Failed to query log');
118-
return setLogsStore((store) => setLogData(store, [], []));
119-
} finally {
120-
setLoading(false);
121-
}
122-
};
118+
const { records, fields } = logs;
119+
const jqFilteredData = isJqSearch(instantSearchValue) ? await jqSearch(records, instantSearchValue) : [];
120+
setLogsStore((store) => setLogData(store, records, fields, jqFilteredData));
121+
},
122+
onError: (data: AxiosError) => {
123+
const errorMessage = data.response?.data as string;
124+
setError(_.isString(errorMessage) && !_.isEmpty(errorMessage) ? errorMessage : 'Failed to query logs');
125+
},
126+
},
127+
);
123128

124129
const resetData = () => {
125130
_dataRef.current = null;
@@ -133,7 +138,7 @@ export const useQueryLogs = () => {
133138
getColumnFilters,
134139
sort: querySearch.sort,
135140
error,
136-
loading: loading,
141+
loading: logsLoading || logsRefetching,
137142
getQueryData,
138143
resetData,
139144
};

src/pages/Stream/Views/Explore/LogsView.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import JsonView from './JSONView';
44
import LogTable from './StaticLogTable';
55
import useLogsFetcher from './useLogsFetcher';
66
import LogsViewConfig from './LogsViewConfig';
7+
import _ from 'lodash';
78

89
const LogsView = (props: { schemaLoading: boolean; infoLoading: boolean }) => {
910
const { schemaLoading, infoLoading } = props;
1011
const { errorMessage, hasNoData, showTable, isFetchingCount, logsLoading } = useLogsFetcher({
1112
schemaLoading,
1213
infoLoading,
1314
});
15+
1416
const [viewMode] = useLogsStore((store) => store.viewMode);
1517
const viewOpts = {
1618
errorMessage,

src/pages/Stream/hooks/useParamsController.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { TimeRange, useLogsStore, logsStoreReducers } from '@/pages/Stream/provi
33
import { useSearchParams } from 'react-router-dom';
44
import _ from 'lodash';
55
import { FIXED_DURATIONS } from '@/constants/timeConstants';
6+
import { LOG_QUERY_LIMITS } from '@/pages/Stream/providers/LogsProvider';
67
import dayjs from 'dayjs';
78
import timeRangeUtils from '@/utils/timeRangeUtils';
89
import moment from 'moment-timezone';
@@ -14,7 +15,6 @@ const { setTimeRange, onToggleView, setPerPage, setCustQuerySearchState } = logs
1415
const { applySavedFilters } = filterStoreReducers;
1516
const timeRangeFormat = 'DD-MMM-YYYY_HH-mmz';
1617
const keys = ['view', 'rows', 'interval', 'from', 'to', 'query', 'filterType'];
17-
const FIXED_ROWS = ['50', '100', '150', '200'];
1818

1919
const dateToParamString = (date: Date) => {
2020
return formatDateWithTimezone(date, timeRangeFormat);
@@ -109,7 +109,7 @@ const useParamsController = () => {
109109
if (['table', 'json'].includes(presentParams.view) && presentParams.view !== storeAsParams.view) {
110110
setLogsStore((store) => onToggleView(store, presentParams.view as 'table' | 'json'));
111111
}
112-
if (storeAsParams.rows !== presentParams.rows && FIXED_ROWS.includes(presentParams.rows)) {
112+
if (storeAsParams.rows !== presentParams.rows && LOG_QUERY_LIMITS.includes(_.toNumber(presentParams.rows))) {
113113
setLogsStore((store) => setPerPage(store, _.toNumber(presentParams.rows)));
114114
}
115115

@@ -161,7 +161,7 @@ const useParamsController = () => {
161161
if (presentParams.view && presentParams.view !== storeAsParams.view) {
162162
setLogsStore((store) => onToggleView(store, presentParams.view as 'table' | 'json'));
163163
}
164-
if (storeAsParams.rows !== presentParams.rows && FIXED_ROWS.includes(presentParams.rows)) {
164+
if (storeAsParams.rows !== presentParams.rows && LOG_QUERY_LIMITS.includes(_.toNumber(presentParams.rows))) {
165165
setLogsStore((store) => setPerPage(store, _.toNumber(presentParams.rows)));
166166
}
167167

0 commit comments

Comments
 (0)