diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index ecf5cba07..6271458b4 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -1,4 +1,3 @@ -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useContext, useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { useNavigate } from "react-router-dom"; @@ -13,7 +12,8 @@ import { FETCH_ERROR_MESSAGE, } from "./constants/constants"; import { AuthContext } from "./contexts/authContext"; -import { autoLogin, getGlobalVariables, getHealth } from "./controllers/API"; +import { autoLogin } from "./controllers/API"; +import { useGetHealthQuery } from "./controllers/API/queries/health"; import { useGetVersionQuery } from "./controllers/API/queries/version"; import { setupAxiosDefaults } from "./controllers/API/utils"; import useTrackLastVisitedPath from "./hooks/use-track-last-visited-path"; @@ -25,21 +25,22 @@ import useFlowsManagerStore from "./stores/flowsManagerStore"; import { useFolderStore } from "./stores/foldersStore"; export default function App() { - const queryClient = new QueryClient(); - useTrackLastVisitedPath(); - const [fetchError, setFetchError] = useState(false); const isLoading = useFlowsManagerStore((state) => state.isLoading); const { isAuthenticated, login, setUserData, setAutoLogin, getUser } = useContext(AuthContext); const setLoading = useAlertStore((state) => state.setLoading); const refreshStars = useDarkStore((state) => state.refreshStars); - const navigate = useNavigate(); const dark = useDarkStore((state) => state.dark); const isLoadingFolders = useFolderStore((state) => state.isLoadingFolders); - const [isLoadingHealth, setIsLoadingHealth] = useState(false); + const { + data: healthData, + isFetching: fetchingHealth, + isError: isErrorHealth, + refetch, + } = useGetHealthQuery(); useEffect(() => { if (!dark) { document.getElementById("body")!.classList.remove("dark"); @@ -102,49 +103,6 @@ export default function App() { }); }; - useEffect(() => { - checkApplicationHealth(); - // Timer to call getHealth every 5 seconds - const timer = setInterval(() => { - getHealth() - .then(() => { - onHealthCheck(); - }) - .catch(() => { - setFetchError(true); - }); - }, 20000); // 20 seconds - - // Clean up the timer on component unmount - return () => { - clearInterval(timer); - }; - }, []); - - const checkApplicationHealth = () => { - setIsLoadingHealth(true); - getHealth() - .then(() => { - onHealthCheck(); - }) - .catch(() => { - setFetchError(true); - }); - - setTimeout(() => { - setIsLoadingHealth(false); - }, 2000); - }; - - const onHealthCheck = () => { - setFetchError(false); - //This condition is necessary to avoid infinite loop on starter page when the application is not healthy - if (isLoading === true && window.location.pathname === "/") { - navigate("/all"); - window.location.reload(); - } - }; - const isLoadingApplication = isLoading || isLoadingFolders; return ( @@ -161,11 +119,16 @@ export default function App() { value !== "ok")) + } setRetry={() => { - checkApplicationHealth(); + console.log("retrying"); + refetch(); }} - isLoadingHealth={isLoadingHealth} + isLoadingHealth={fetchingHealth} > } diff --git a/src/frontend/src/controllers/API/index.ts b/src/frontend/src/controllers/API/index.ts index ebb5d1247..e586e2803 100644 --- a/src/frontend/src/controllers/API/index.ts +++ b/src/frontend/src/controllers/API/index.ts @@ -319,22 +319,6 @@ export async function getVersion() { return response.data; } -/** - * Fetches the health status of the API. - * - * @returns {Promise>} A promise that resolves to an AxiosResponse containing the health status. - */ -export async function getHealth() { - return await api.get("/health").catch((e) => { - if (e.code === "ECONNABORTED") { - console.log("request cancelled"); - } else { - // raise error to be caught by the caller - throw e; - } - }); // Health is the only endpoint that doesn't require /api/v1 -} - /** * Fetches the build status of a flow. * @param {string} flowId - The ID of the flow to fetch the build status for. diff --git a/src/frontend/src/controllers/API/queries/health/index.ts b/src/frontend/src/controllers/API/queries/health/index.ts new file mode 100644 index 000000000..0a1e53bf4 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/health/index.ts @@ -0,0 +1 @@ +export * from "./use-get-health"; diff --git a/src/frontend/src/controllers/API/queries/health/use-get-health.ts b/src/frontend/src/controllers/API/queries/health/use-get-health.ts new file mode 100644 index 000000000..bf9d392e4 --- /dev/null +++ b/src/frontend/src/controllers/API/queries/health/use-get-health.ts @@ -0,0 +1,52 @@ +import { keepPreviousData } from "@tanstack/react-query"; +import { useQueryFunctionType } from "../../../../types/api"; +import { api } from "../../api"; +import { UseRequestProcessor } from "../../services/request-processor"; + +interface getHealthResponse { + status: string; + chat: string; + db: string; + folder: string; + variables: string; +} + +export const useGetHealthQuery: useQueryFunctionType< + undefined, + getHealthResponse +> = (_, onFetch) => { + const { query } = UseRequestProcessor(); + + const responseFn = (data: getHealthResponse) => { + if (!onFetch) return data; + if (typeof onFetch === "function") return onFetch(data); + switch (onFetch) { + default: + return data; + } + }; + + /** + * Fetches the health status of the API. + * + * @returns {Promise>} A promise that resolves to an AxiosResponse containing the health status. + */ + async function getHealthFn() { + return await api.get("/health_check"); + // Health is the only endpoint that doesn't require /api/v1 + } + + const queryResult = query( + ["useGetHealthQuery"], + async () => { + const result = await getHealthFn(); + return responseFn(result.data); + }, + { + placeholderData: keepPreviousData, + refetchInterval: 20000, + }, + ); + + return queryResult; +};