Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Footer Count Error #296

Merged
merged 12 commits into from
Aug 20, 2024
46 changes: 2 additions & 44 deletions src/hooks/useQueryLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { SortOrder, type Log, type LogsData, type LogsSearch } from '@/@types/pa
import { getQueryLogsWithHeaders, getQueryResultWithHeaders } from '@/api/query';
import { StatusCodes } from 'http-status-codes';
import useMountedState from './useMountedState';
import { useCallback, useEffect, useRef } from 'react';
import { useCallback, useRef } from 'react';
import { useLogsStore, logsStoreReducers, LOAD_LIMIT, isJqSearch } from '@/pages/Stream/providers/LogsProvider';
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
import { useQueryResult } from './useQueryResult';
import _ from 'lodash';
import { AxiosError } from 'axios';
import jqSearch from '@/utils/jqSearch';
import { useGetLogStreamSchema } from './useGetLogStreamSchema';

const { setLogData, setTotalCount } = logsStoreReducers;
const { setLogData } = logsStoreReducers;

type QueryLogs = {
streamName: string;
Expand All @@ -32,7 +31,6 @@ export const useQueryLogs = () => {
const _dataRef = useRef<Log[] | null>(null);
const [error, setError] = useMountedState<string | null>(null);
const [loading, setLoading] = useMountedState<boolean>(false);
const [isFetchingCount, setIsFetchingCount] = useMountedState<boolean>(false);
const [pageLogData, setPageLogData] = useMountedState<LogsData | null>(null);
const { getDataSchema } = useGetLogStreamSchema();
const [querySearch, setQuerySearch] = useMountedState<LogsSearch>({
Expand Down Expand Up @@ -111,44 +109,6 @@ export const useQueryLogs = () => {
}
};

// fetchQueryMutation is used only on fetching count
// refactor this hook if you want to use mutation anywhere else
const { fetchQueryMutation } = useQueryResult();

useEffect(() => {
const { fields = [], records = [] } = fetchQueryMutation.data || {};
const firstRecord = _.first(records);
if (_.includes(fields, 'count') && _.includes(_.keys(firstRecord), 'count')) {
const count = _.get(firstRecord, 'count', 0);
setLogsStore((store) => setTotalCount(store, _.toInteger(count)));
}
}, [fetchQueryMutation.data]);

const fetchCount = () => {
try {
setIsFetchingCount(true);
const defaultQuery = `select count(*) as count from ${currentStream}`;
const query = isQuerySearchActive
? custSearchQuery.replace(/SELECT[\s\S]*?FROM/i, 'SELECT COUNT(*) as count FROM')
: defaultQuery;
if (currentStream && query?.length > 0) {
const logsQuery = {
streamName: currentStream,
startTime: timeRange.startTime,
endTime: timeRange.endTime,
access: [],
};
fetchQueryMutation.mutate({
logsQuery,
query,
onSuccess: () => setIsFetchingCount(false),
});
}
} catch (e) {
console.log(e);
}
};

const resetData = () => {
_dataRef.current = null;
setPageLogData(null);
Expand All @@ -164,7 +124,5 @@ export const useQueryLogs = () => {
loading: loading,
getQueryData,
resetData,
fetchCount,
isFetchingCount,
};
};
76 changes: 65 additions & 11 deletions src/hooks/useQueryResult.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
import { getQueryResultWithHeaders } from '@/api/query';
import { getQueryResultWithHeaders, getQueryResult } from '@/api/query';
import { LogsQuery } from '@/@types/parseable/api/query';
import { notifications } from '@mantine/notifications';
import { isAxiosError, AxiosError } from 'axios';
import { IconCheck, IconFileAlert } from '@tabler/icons-react';
import { useMutation } from 'react-query';
import { useMutation, useQuery } from 'react-query';
import { logsStoreReducers, useLogsStore } from '@/pages/Stream/providers/LogsProvider';
import _ from 'lodash';
import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';

type QueryData = {
logsQuery: LogsQuery;
query: string;
onSuccess?: () => void;
};

export const useQueryResult = () => {
const fetchQueryHandler = async (data: QueryData) => {
const response = await getQueryResultWithHeaders(data.logsQuery, data.query);
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.data;
};
type CountResponse = {
count: number;
}[];

const fetchQueryHandlerWithFields = async (data: QueryData) => {
const response = await getQueryResultWithHeaders(data.logsQuery, data.query);
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.data;
};

const fetchQueryMutation = useMutation(fetchQueryHandler, {
const fetchQueryHandler = async (data: QueryData) => {
const response = await getQueryResult(data.logsQuery, data.query);
Koustavd18 marked this conversation as resolved.
Show resolved Hide resolved
if (response.status !== 200) {
throw new Error(response.statusText);
}
return response.data;
};

export const useQueryResult = () => {
const fetchQueryMutation = useMutation(fetchQueryHandlerWithFields, {
onError: (data: AxiosError) => {
if (isAxiosError(data) && data.response) {
notifications.update({
Expand Down Expand Up @@ -48,3 +63,42 @@ export const useQueryResult = () => {

return { fetchQueryMutation };
};

export const useFetchCount = () => {
const [currentStream] = useAppStore((store) => store.currentStream);
const { setTotalCount } = logsStoreReducers;
const [custQuerySearchState] = useLogsStore((store) => store.custQuerySearchState);
const [timeRange, setLogsStore] = useLogsStore((store) => store.timeRange);
const { isQuerySearchActive, custSearchQuery } = custQuerySearchState;

const defaultQuery = `select count(*) as count from ${currentStream}`;
const query = isQuerySearchActive
? custSearchQuery.replace(/SELECT[\s\S]*?FROM/i, 'SELECT COUNT(*) as count FROM')
: defaultQuery;

const logsQuery = {
streamName: currentStream || '',
startTime: timeRange.startTime,
endTime: timeRange.endTime,
access: [],
};
const {
isLoading: isCountLoading,
isRefetching: isCountRefetching,
refetch: countRefetch,
} = useQuery(['fetchCount', logsQuery], () => fetchQueryHandler({ logsQuery, query }), {
onSuccess: (data: CountResponse) => {
const footerCount = _.first(data)?.count;
footerCount && setLogsStore((store) => setTotalCount(store, footerCount));
},
Koustavd18 marked this conversation as resolved.
Show resolved Hide resolved
refetchOnWindowFocus: false,
retry: false,
enabled: currentStream !== null,
});

return {
isCountLoading,
isCountRefetching,
countRefetch,
};
};
8 changes: 5 additions & 3 deletions src/pages/Stream/Views/Explore/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,16 @@ const LimitControl: FC = () => {
);
};

const Footer = (props: { loaded: boolean; isLoading: boolean; hasNoData: boolean }) => {
const Footer = (props: { loaded: boolean; hasNoData: boolean; isFetchingCount: boolean }) => {
const [currentStream] = useAppStore((store) => store.currentStream);
const [tableOpts, setLogsStore] = useLogsStore((store) => store.tableOpts);
const [filteredData] = useLogsStore((store) => store.data.filteredData);
const { totalPages, currentOffset, currentPage, perPage, headers, totalCount } = tableOpts;

const onPageChange = useCallback((page: number) => {
setLogsStore((store) => setPageAndPageData(store, page));
}, []);
const [currentStream] = useAppStore((store) => store.currentStream);

const pagination = usePagination({ total: totalPages ?? 1, initialPage: 1, onChange: onPageChange });
const onChangeOffset = useCallback(
(key: 'prev' | 'next') => {
Expand Down Expand Up @@ -137,7 +139,7 @@ const Footer = (props: { loaded: boolean; isLoading: boolean; hasNoData: boolean
<Stack w="100%" justify="center" align="flex-start">
<TotalLogsCount
hasTableLoaded={props.loaded}
isFetchingCount={props.isLoading}
isFetchingCount={props.isFetchingCount}
isTableEmpty={props.hasNoData}
/>
</Stack>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/Stream/Views/Explore/JSONView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,14 @@ const TableContainer = (props: { children: ReactNode }) => {
};

const JsonView = (props: {
isFetchingCount: boolean;
errorMessage: string | null;
hasNoData: boolean;
showTable: boolean;
isFetchingCount: boolean;
}) => {
const [maximized] = useAppStore((store) => store.maximized);

const { isFetchingCount, errorMessage, hasNoData, showTable } = props;
Koustavd18 marked this conversation as resolved.
Show resolved Hide resolved
const { errorMessage, hasNoData, showTable } = props;
const [isSearching, setSearching] = useState(false);
const primaryHeaderHeight = !maximized
? PRIMARY_HEADER_HEIGHT + STREAM_PRIMARY_TOOLBAR_CONTAINER_HEIGHT + STREAM_SECONDARY_TOOLBAR_HRIGHT
Expand Down Expand Up @@ -214,7 +214,7 @@ const JsonView = (props: {
) : (
<ErrorView message={errorMessage} />
)}
<Footer loaded={showTable} isLoading={isFetchingCount} hasNoData={hasNoData} />
<Footer loaded={showTable} hasNoData={hasNoData} isFetchingCount={props.isFetchingCount} />
</TableContainer>
);
};
Expand Down
7 changes: 4 additions & 3 deletions src/pages/Stream/Views/Explore/LogsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import useLogsFetcher from './useLogsFetcher';

const LogsView = (props: { schemaLoading: boolean }) => {
const { schemaLoading } = props;
const { errorMessage, isFetchingCount, hasNoData, showTable } = useLogsFetcher({ schemaLoading });
const { errorMessage, hasNoData, showTable, isFetchingCount } = useLogsFetcher({
schemaLoading,
});
const [viewMode] = useLogsStore((store) => store.viewMode);

const viewOpts = {
isFetchingCount,
errorMessage,
hasNoData,
showTable,
isFetchingCount,
};
return viewMode === 'table' ? <LogTable {...viewOpts} /> : <JsonView {...viewOpts} />;
};
Expand Down
6 changes: 3 additions & 3 deletions src/pages/Stream/Views/Explore/StaticLogTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ interface SectionRefs {
}

const LogTable = (props: {
isFetchingCount: boolean;
errorMessage: string | null;
hasNoData: boolean;
showTable: boolean;
isFetchingCount: boolean;
}) => {
const { isFetchingCount, errorMessage, hasNoData, showTable } = props;
Koustavd18 marked this conversation as resolved.
Show resolved Hide resolved
const { errorMessage, hasNoData, showTable } = props;
const [containerRefs, _setContainerRefs] = useState<SectionRefs>({
activeSectionRef: useRef<'left' | 'right'>('left'),
leftSectionRef: useRef<HTMLDivElement>(null),
Expand Down Expand Up @@ -180,7 +180,7 @@ const LogTable = (props: {
) : (
<ErrorView message={errorMessage} />
)}
<Footer loaded={showTable} isLoading={isFetchingCount} hasNoData={hasNoData} />
<Footer loaded={showTable} hasNoData={hasNoData} isFetchingCount={props.isFetchingCount} />
</TableContainer>
);
};
Expand Down
19 changes: 14 additions & 5 deletions src/pages/Stream/Views/Explore/useLogsFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ import { useAppStore } from '@/layouts/MainLayout/providers/AppProvider';
import { useEffect } from 'react';
import { useLogsStore, logsStoreReducers } from '../../providers/LogsProvider';
import { useQueryLogs } from '@/hooks/useQueryLogs';
import { useFetchCount } from '@/hooks/useQueryResult';

const { setCleanStoreForStreamChange } = logsStoreReducers;

const useLogsFetcher = (props: { schemaLoading: boolean }) => {
const { schemaLoading } = props;
const [currentStream] = useAppStore((store) => store.currentStream);
const [tableOpts, setLogsStore] = useLogsStore((store) => store.tableOpts);
const [{ tableOpts, timeRange }, setLogsStore] = useLogsStore((store) => store);
const { currentOffset, currentPage, pageData } = tableOpts;
const { getQueryData, loading: logsLoading, error: errorMessage, fetchCount, isFetchingCount } = useQueryLogs();
const { getQueryData, loading: logsLoading, error: errorMessage } = useQueryLogs();
const { countRefetch, isCountLoading, isCountRefetching } = useFetchCount();
Koustavd18 marked this conversation as resolved.
Show resolved Hide resolved
const hasContentLoaded = schemaLoading === false && logsLoading === false;
const hasNoData = hasContentLoaded && !errorMessage && pageData.length === 0;
const showTable = hasContentLoaded && !hasNoData && !errorMessage;
Expand All @@ -22,17 +24,24 @@ const useLogsFetcher = (props: { schemaLoading: boolean }) => {
useEffect(() => {
if (currentPage === 0 && currentOffset === 0) {
getQueryData();
fetchCount();
countRefetch();
}
}, [currentPage]);
}, [currentPage, currentStream, timeRange]);

useEffect(() => {
if (currentOffset !== 0 && currentPage !== 0) {
getQueryData();
}
}, [currentOffset]);

return { logsLoading, errorMessage, isFetchingCount, hasContentLoaded, hasNoData, showTable };
return {
logsLoading,
errorMessage,
hasContentLoaded,
hasNoData,
showTable,
isFetchingCount: isCountLoading || isCountRefetching,
};
};

export default useLogsFetcher;
Loading